Is it necessary to set large objects to null
when implementing a Dispose()
method?
问题:
回答1:
Not usually.
The garbage collector looks for rooted objects, and circular dependencies don't prevent collection if neither object is rooted.
There is a caveat: if object A has a reference to object B, and object B is being disposed, you may want to clean up that relationship or else you could end up with a leak. The most common place this surfaces is in event handlers (the reference from A->B is one that B controls, because it subscribed to an event on A). In this case, if A is still rooted, B cannot be collected even though it's been disposed.
回答2:
If a class has a Dispose method the best practice is to call it. the reason behind that is that Dispose runs when called, whereas setting the object to null simply adds a entry to the Finalize queue in GC, and we cannot determine when GC will run.
There is no performance benefit in implementing the Dispose method on types that use only managed resources (such as arrays) because they are automatically reclaimed by the garbage collector. Use the Dispose method primarily on managed objects that use native resources and on COM objects that are exposed to the .NET Framework. Managed objects that use native resources (such as the FileStream class) implement the IDisposable interface.
An elegant means of inoking Dispose that have adopted is using the "using" construct. For those of you who may not be familiar with the construct, it provide a means to implicity invoke Dispose() on an instance that implements IDisposable even if an exception is thrown durring the operation. The following is an example of the using construct:
using(DisposableClass dc = new DisposableClass())
{
dc.PerformActionOnUmanagedResources();
dc.PerformAnotherActionOnUmanagedResources();
}
In the previous example, if an exception was thrown in the PerformActionOnUmanagedResources() method, although the PerformAnotherActionOnUmanagedResources() method would not be processed, the using block will still implicity invoke the Dispose method on dc ensuring the realese of any unmanaged resources.
回答3:
The purpose of a dispose method is to release all resources associated with your class, and the parent's class by calling the base class dispose method. Have a read of this link, it should make things a little clearer:
http://msdn.microsoft.com/en-us/library/fs2xkftw.aspx
回答4:
what do you mean by "large object"?
You should at least call Dispose() on any member implementing IDisposable, though.
回答5:
It isn't necessary as others have pointed out, but it is good practice and helps with debugging.
Once an object has finished with a pointer it is using then setting it to null helps prevent reuse of that object later (you'll get an null reference exception).
The same logic applies to setting member pointers to null in C++ destructors once you have deleted them. There is no need to do it, but it helps with troubleshooting later.
回答6:
Think about the purpose of Disposable methods for a bit: it's usually because you're holding some resource that won't be released during garbage collection. This is usually something like a database connection or a file handle. Thus, once the Dispose method has been called, all those resources have been released.
I'd argue that having nulls floating around is more harmful that having "zombie" objects floating around.