Why do some people use the Finalize
method over the Dispose
method?
In what situations would you use the Finalize
method over the Dispose
method and vice versa?
-
Finalize gets called by the GC when this object is no longer in use.
Dispose is just a normal method which the user of this class can call to release any resources.
If user forgot to call Dispose and if the class have Finalize implemented then GC will make sure it gets called.
-
The finalizer method is called when your object is garbage collected and you have no guarantee when this will happen (you can force it, but it will hurt performance).
The
Dispose
method on the other hand is meant to be called by the code that created your class so that you can clean up and release any resources you have acquired (unmanaged data, database connections, file handles, etc) the moment the code is done with your object.The standard practice is to implement
IDisposable
andDispose
so that you can use your object in ausing
statment. Such asusing(var foo = new MyObject()) { }
. And in your finalizer, you callDispose
, just in case the calling code forgot to dispose of you.itowlson : You need to be a bit careful about calling Dispose from your Finalize implementation -- Dispose may also dispose managed resources, which you don't want to touch from your finalizer, as they may already have been finalized themselves.Samuel : @itowlson: Checking for null combined with the assumption that objects can be disposed of twice (with second call doing nothing) should be good enough.Brody : The standard IDisposal pattern and the hidden implementation of a Dispose(bool) to handle disposing managed components optional seems to cater for that issue.peterchen : Brody, I just wish this pattern would be easier to implement.... -
Finalize is the backstop method, called by the garbage collector when it reclaims an object. Dispose is the "deterministic cleanup" method, called by applications to release valuable native resources (window handles, database connections, etc.) when they are no longer needed, rather than leaving them held indefinitely until the GC gets round to the object.
As the user of an object, you always use Dispose. Finalize is for the GC.
As the implementer of a class, if you hold managed resources that ought to be disposed, you implement Dispose. If you hold native resources, you implement both Dispose and Finalize, and both call a common method that releases the native resources. These idioms are typically combined through a private Dispose(bool disposing) method, which Dispose calls with true, and Finalize calls with false. This method always frees native resources, then checks the disposing parameter, and if it is true it disposes managed resources and calls GC.SuppressFinalize.
-
99% of the time, you should not have to worry about either. :) But, if your objects hold references to non-managed resources (window handles, file handles, for example), you need to provide a way for your managed object to release those resources. Finalize gives implicit control over releasing resources. It is called by the garbage collector. Dispose is a way to give explicit control over a release of resources and can be called directly.
There is much much more to learn about the subject of Garbage Collection, but that's a start.
Samuel : I'm pretty sure more than 1% of C# applications use databases: where you *have* to worry about IDisposable SQL stuff.Darren Clark : Also, you should implement IDisposable if you encapsulate IDisposables. Which probably covers the other 1%.JP Alioto : @Samuel: I don't see what databases has to do with it. If you are talking about closing connections, that's fine, but that's a different matter. You don't have to dispose objects to close connections in a timely manner.Brody : @JP: But the Using(...) pattern makes it so much simpler to cope with.JP Alioto : Agreed, but that's exactly the point. The using pattern hides the call to Dispose for you. -
Others have already covered the difference between
Dispose
and finalize (btw the finalize method is still called a destructor in the language specification), so I'll just add a little about the scenarios where the finalize method comes in handy.Some types encapsulates disposable resources in a manner where it is easy to use and dispose of them in a single action. The general usage is often like this. Open, read or write, close (Dispose). It fits very well with the
using
construct.Others are a bit more difficult.
WaitEventHandles
for instances are not used like this as they are used to signal from one thread to another. The question then becomes who should callDispose
on these? As a safeguard types like these implement a finalize method, which makes sure resources are disposed when the instance is no longer referenced by the application. -
Finalize
- Finalizers should always be protected, not public or private so that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalize method
- Finalizers should release unmanaged resources only.
- The framework does not guarantee that a finalizer will execute at all on any given instance.
- Never allocate memory in finalizers or call virtual methods from finalizers.
- Avoid synchronization and raising unhandled exceptions in the finalizers.
- The execution order of finalizers is non-deterministic—in other words, you can't rely on another object still being available within your finalizer.
- Do not define finalizers on value types.
- Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resources—and if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether.
Dispose
- Implement IDisposable on every type that has a finalizer
- Ensure that an object is made unusable after making a call to the Dispose method. In other words, avoid using an object after the Dispose method has been called on it.
- Call Dispose on all IDisposable types once you are done with them
- Allow Dispose to be called multiple times without raising errors.
- Suppress later calls to the finalizer from within the Dispose method using the GC.SuppressFinalize method
- Avoid creating disposable value types
- Avoid throwing exceptions from within Dispose methods
Dispose/Finalized Pattern
- Microsoft recommends that you implement both Dispose and Finalize when working with unmanaged resources. The Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Dispose method explicitly.
- Cleanup the unmanaged resources in the Finalize method and the managed ones in the Dispose method, when the Dispose/Finalize pattern has been used in your code.
code example and additional resources are here: mgznet.com/disposedAndFinalized.aspx
0 comments:
Post a Comment