Dispose, Finalization, and Resource Management

  1. 云栖社区>
  2. 博客>
  3. 正文

Dispose, Finalization, and Resource Management

胡庆访 2016-05-05 16:15:09 浏览836

原文见:DG Update: Dispose, Finalization, and Resource Management

*Explicit Cleanup & Implicit Cleanup

*实现Finalizer的类,无可避免地加大了系统的负担。最小的开支来自于,至少要把这个对象,加入Finalizable Object列表。


Dispose Pattern:

Do implement the dispose pattern when your type is unsealed and contains resources that explicitly need to be or can be freed.

Do fully implement the dispose pattern on classes with disposable subtypes, even if the base type does not own resources.(eg. Stream)

Do implement IDispoable only on classes where a class in its parent hierarchy has not already done so.


Do create or override the protected irtual void Dispose(bool disposing) method to encapsulate all of your cleanup logic.

这个虚方法的参数bool值表示是Explicit Cleanup还是Implicit Cleanup。因为如果是Implicity CleanUp,则表示是因为GC引起的调用,所以这时,代码最好不要使用类型中的引用类型字段。

Do make a call to your base class’s Dispose(bool disposing) method (if available) as the last operation in your Dispose(bool) implementation.

Do implement a finalizer if your object is responsible for controlling the lifetime of at least one resource which does not have its own finalizer.

Do not re-implement the IDisposable interface, override void Dispose(), or override Finalize if a base type in your class hierarchy has already defined them according to this pattern.

Do not create any other variations of the Dispose method other than the two specified here: void Dispose() and void Dispose(bool disposing).



Do implement IDisposable on every type that has a finalizer.

Do allow your Dispose method to be called more than once.

Do transitively dispose of any disposable fields defined in your type from your Dispose method.

Consider setting disposed fields to null before actually executing dispose when reference cycles in an object graph are possible.

Avoid throwing an exception from within Dispose except under critical situations where the containing process has been corrupted(leaks, inconsistent shared state, etc.).

Consider making your object unusable after calling Dispose.

Do implement a Close method for cleanup pruposes if such terminology is standard, for example as with a file or socket.

Consider nulling out large managed object fields in your Dispose method.

Avoid createing disposable value types, and never create a value type which manages the lifetime of unmanaged resources disrectly.

Consider disposing of any IDisposable object instances when your are done with them.

Do not swallow exceptions arising from a call to Dispose.



Do carefully consider any case where you think a finalizer is needed.

Do make your Finalize method protected, not public or private.(C#/C++ developers do not need to worry about this.)

Do free only owned unmanaged resources in your type’s Finalize method.

Do not directly call the Finalize method.

Do gracefully handle situations in which your finalizer is invoked more than once.

Do not assume your object is unreachable during finalization.

Do not assume your finalizer will always run.

Consider using a critical finalizable object(SafeHandle, or any type whose type hierarchy contains CriticalFinalizerObject) for situations where a finalizer absolutely must execute even in the face of AppDomain unloads and rude thread aborts.

Avoid allocating memory in finalizers.

Do not allocate memory from within a critical finalizer, ofr from SafeHandle’s ReleaseHandle method, at least not on the success paths.

Do not call virtual members from finalizers except for in very controlled designs, such as the Dispose(bool) method outlined in the pattern above.

Do write finalizers that are tolerant of partially constructed instances(i.e. objects whose constructors may have never completed).

Do write finalizers that are threading-agnostic.

Avoid blocking execution from within a finalizer.

Do not raise unhandled exceptions or otherwise leak exceptions from your finalizer, except for in very system critical circumstances(such as OutOfMemory, for example).

Avoid resurrecting yourself by setting a reference to a rooted context, i.e. through a GC reachable reference such as a static field or reachable objects to which you still have a reference.

Do not assume that avoiding resurrecting yourself prevents you from being rooted again after or during finalization.

Do not modify thread context from within your finalizer, as it will end up polluting the finalizer thread.

Do not assume that, because some object is reachable while you’re being finalized, that it has not been or is not in the process of being finalized-e.g., static fields, common infrastructure, and so on.

Do not define finalizers on value types.



Do use SafeHandle for warpping scarce unmanaged resources such as OS handles, preferring it to IntPtr or Int32 representations for native handles.


HandleCollector and Memory Pressure

Avoid making calls to GC.Collect() and GC.GetTotalMemory(true) with the intent of controlling the GC’s policy to provoke collecting resources eagerly.


+ 关注