| Profilo di StevenDevelopmentalBlogElenchi | Guida |
|
06 gennaio Object Finalization : IDisposable, Dispose(), Destructors and Garbage CollectionI apologise for the long title, but I wanted to be clear about what this post will cover. I was recently updating some of Readify’s courseware and was looking at our Garbage Collection section; that prompted this post. Concepts First lets define 2 concepts: Dispose() method and the Finalizer. In C#, the Finalizer is known as the ‘Destructor’ and is a special method that follows this syntax:
As you can see, a destructor follows the constructor logic, but has a tilda ~ in front. In VB.Net there is no equivalent, however you can override the Object.Finalize method instead (which incidentally you can’t do in C#). So that is essentially the direct equivalent. Incidentally, because every class inherits from object, your class already has a Finalizer, it just doesn’t do anything until you implement it yourself. Dispose() is a method that you define. There is an interface called IDisposable which will force you to implement this method. If you don’t define it, your class doesn’t have it. What Are They Used For Both the Finalizer and the Dispose() method are used for cleaning up your objects. This might be closing database connections, letting go of a disk file, or closing a stream from your serial port. It also means releasing handles to unmanaged resources such as pointers and COM artefacts. The Finalizer (destructor) is called when the garbage collector cleans up your object. But garbage collectors are unpredictable: they will clean up your object whenever they feel like it. This is known as ‘non-deterministic finalization’ because we can’t determine when the object will be cleaned up. Also, the destructor is not a proper method so you cannot call it from your code. The Dispose() method is just that: a method that you can call whenever you like. This makes it ‘deterministic’ in that we can determine when the cleanup will occur: when we call the method. By implementing IDisposable we are also telling other artefacts that we have that special cleanup method and can be called. A good example of that is the “using” statement. Here is an example:
In the above example a StreamReader object is created and utilised. The ‘using’ statement ensures that the Dispose() method is called at the closing bracket. In fact, it will do this even if an exception occurs within the ‘using’ scope. However, you can only use this syntax on classes that implement IDisposable. Which Do I Use If you have nothing to cleanup (and your sub-classes or base class have nothing to cleanup) then you don’t need to worry about either. However when you have resources to cleanup, then you should really implement both. The reason for this is simple: Provide Dispose() method for deterministic finalization, and provide a destructor in case consumers don’t call the Dispose() method. And for those of you (like me) who hate to waste white space on duplicate code, you can call the Dispose() method from your finalizer, however it is best to consider some Microsoft recommended best practises when doing so. Pattern For Finalization This pattern is based on this article by Joe Duffy. The following example illustrates the pattern best:
As you can see, there is a bool switch to determine if the Dispose logic applies to finalization or not. This pattern has some advantages when it comes to inheritance. For example, overriding the Dispose(bool disposing) method in a sub-class lets you customise how finalization will occur, without needing to provide the destructor or Dispose() methods (since via inheritance your class already has those methods and implements IDisposable). Also, we track if the object has already been disposed so that we don’t do it again. Finally, the call to GC.SuppressFinalze(this) means that since the object has been properly disposed, there is no need to call the destructor (ie. suppress finalization of this object). Make sure that call goes after the call to Dispose(true) : this ensures that if the Dispose method fails (raises exception) that the destructor will still execute again later and reattempt to cleanup the object. Technorati Tags: Garbage Collector,SuppressFinalize,IDisposable,Dispose,Finalizer,Destructor,Pattern Commenti (2)Per aggiungere un commento, accedi con il tuo Windows Live ID (se utilizzi Hotmail, Messenger o Xbox LIVE possiedi già un Windows Live ID). Accedi Non hai ancora un Windows Live ID? Registrati
RiferimentiL'URL di riferimento per questo intervento è: http://stevennagy.spaces.live.com/blog/cns!B2EFDBF0964586B3!329.trak Blog che fanno riferimento a questo intervento
|
|
|