C#:以分配的逆序排列资源是否有优势?

许多年前,我曾被告诫,尽可能以相反的顺序释放资源以分配资源。 那是:

block1 = malloc( ... ); block2 = malloc( ... ); ... do stuff ... free( block2 ); free( block1 ); 

我想在640K MS-DOS机器上,这可以最小化堆碎片。 在C#/ .NET应用程序中执行此操作是否有任何实际优势,或者这种习惯是否已经超过其相关性?

如果您的资源创建得很好,这应该不重要(多)。

但是,许多创建不良的库没有进行适当的检查。 以与其分配相反的方式处置资源通常意味着您首先处理依赖于其他资源的资源 – 这可以防止写得不好的库导致问题。 (你永远不会丢弃一个资源,然后在这种情况下使用一个依赖于第一个资源的资源。)

这也是一种很好的做法,因为你不会过早地意外地处理某些其他对象所需的资源。

这是一个例子:查看数据库操作。 在关闭/处理命令(使用连接)之前,您不希望关闭/处置连接。

不要打扰。 GarbageCollector保留对堆上的对象进行碎片整理和移动的权利,因此无法确定内容的顺序。

另外,如果你处理A和B以及A引用B,当你处理A时,A处理B应该无关紧要,因为Dispose方法应该可以多次调用而不会抛出exception。

如果你指的是对象上的析构函数被调用的时间,那么这就是垃圾收集器,编程对它的影响很小,并且根据语言定义它是明确的非确定性的。

如果您指的是调用IDisposable.Dispose(),那么这取决于实现IDisposable接口的对象的行为。

通常,对于大多数Framework对象,顺序无关紧要,除非它对调用代码很重要。 但是如果对象A维持对对象B的依赖,并且对象B被处置掉,那么对象A不能做某些事情是非常重要的。

在大多数情况下,Dispose()不是直接调用的,而是作为using或foreach语句的一部分隐式调用,在这种情况下,根据语句嵌入,逆序模式自然会出现。

 using(Foo foo = new Foo()) using(FooDoodler fooDoodler = new FooDoodler(foo)) { // do stuff // ... // fooDoodler automatically gets disposed before foo at the end of the using statement. } 

嵌套的’使用’向你展示’过时’并不是真正开始的,而且很少(在40年的证据之后永远都不会说)。这包括基于堆栈的虚拟机,运行在CMOS上。

[尽管MSDN.com和Duffius试图让它消失,但你知道管理堆栈和堆栈之间的区别。 多么聪明的想法..在太空]

“运行时不会对调用Finalize方法的顺序提供任何保证。例如,假设有一个对象包含指向内部对象的指针。垃圾收集器检测到两个对象都是垃圾。 ,首先调用内部对象的Finalize方法。现在,允许外部对象的Finalize方法访问内部对象并在其上调用方法,但内部对象已经完成,结果可能无法预测。因此,强烈建议Finalize方法不要访问任何内部成员对象。“

http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

所以你可以随心所欲地担心你的LIFO处理语义,但是如果你泄漏了一个,那么Dispose()将以CLR所想的任何顺序被调用。

(这或多或少会说,上面说)