tags:

views:

489

answers:

5

I have the following piece of code, just wanted to check who will call the dispose? is it called automatically.

ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, toolTipText);

Also let say I create a Timer local variable, who will call the dispose, what about memory leaks, as, if I call the dispose right away, the timer event, won't be fired.

Do I need to make sure that in the timer event handler dispose is called, even if I don't have any reference to the timer variable. Also do I need to unregister the event handler for that timer.

Edit:

  • But how to call dispose on ToolTip, if I call it won't show.
  • Also why I need to Dispose the Timer, if I don't have any reference.
  • And Do I need to also unregister the timer event handler?
  • Also does keeping a reference increases the class memory footprint.
A: 

Generally, it's up to the object registering to an event to un-register - not doing so will create memory leaks. You should not rely on a Dispose method doing so.

Dispose is not called automatically, unless you wrap the object in a using() {} statement, or add it to the objects IContainer instance (if it's a designer class). If it's a class variable, you need to make the containing class implement IDisposable and dispose of the instance in it.

thecoop
your answer is not clear, you mean to say I need to keep unnecessary reference to the timer, then unregister the event handler then dispose it?
Priyank Bolia
Yup - you'll need to keep a reference around, then unregister the event when it gets disposed
thecoop
I guess .NET the garbage collector will automatically GC it, if no references, it just might take some additional time, but calling Dispose is not mandatory, and it makes no sense to register event handlers, and call dispose inside them and unregister the event handlers.
Priyank Bolia
+2  A: 

Dispose is a method provided to allow you to release the object immediately. For example an exclusive file stream.

Finalize is a method that automatically releases any resources the object is using once it is no longer being used by your program.

You only need to worry about disposing when the object uses exclusive or finite resources. Examples being the file one, or a database connection. (Note that in both these cases Close is equivalent to disposing)

To answer your question, you are not disposing at all, but letting the finalizer run when it needs to.

Guvante
WinForms controls and components implement IDisposable (because they do hold finite resources like HWNDs or timer handles) and should therefore be disposed rather than waiting for the finaliser.
itowlson
But should I worry about keeping references and dispose off, or let the finalizer do the job. Also does keep a reference increase the class memory footprint.
Priyank Bolia
Keeping a reference does increase the class memory footprint by a few bytes. But this class is a Windows Forms, is that right? Unless you're expecting to create hundreds of thousands of form instances, the memory overhead of one extra reference is below trivial -- just not worth worrying about!
itowlson
one one reference adds up, and unnecessary cluster the class also. You need a reference for timer, tooltip, ... and then you have to add event handlers and dispose them in those event handlers. The overhead looks too big to me, rather than just forcing the GC.
Priyank Bolia
@itowlson: But the loss of HWNDs is pretty trivial as well. Not like there are big restrictions on them. If you are having a hard time keeping track of when an object needs to be disposed, then don't track it unless profiling says it is causing a lot of overhead. At the very least by using any tracking system you are duplicating the work the GC does for you. At worse you are hurting performance by double doing the work and working against yourself overall. Assuming objects *need* to be disposed because there is a Dispose() method is a bit of a premature optimization IMO.
Guvante
+1  A: 

You need to call Dispose on anything that implements IDisposable, or at least make sure something does. For UI components, add them to a form's Controls collection and they'll get disposed when the form closes. For other things you need to keep a reference to them and call dispose appropriately. It may be appropriate to make your class implement IDisposable just to call Dispose on your composed objects.

Sam
I disagree, why to unnecessary keep references, see my edit in the question.
Priyank Bolia
You don't __need__ to call `Dispose()` if you are content with the resources being released during finalization (garbage collection time).
Steve Guidi
You keep (relatively) cheap references so you can avoid holding on to (relatively) scarce or expensive resources.
Jeff Sternal
+4  A: 

ToolTip registers event handlers on the control on which it is shown. It's Hide() method is automatically called when the form's Deactivate event fires. Which will happen when the form is closed. That in turn ensures that its Windows handle is destroyed and event handlers are unregistered. After that there are no disposable objects left.

You can verify this for yourself with Reflector or the Reference Source. Relevant methods are, in order, BaseFormDeactivate, HideAllToolTips, Hide, ClearTopLevelControlEvents.

You don't have to call Dispose(), you don't have a leak.

Hans Passant
Totally confused here, you say not needed, people in other posts says its needed. Also If I don't have any reference to timer class, will it be automatically GC after the event is fired?
Priyank Bolia
I don't think they looked at the code. Every non-static object is GC-ed if there are no references left to it.
Hans Passant
+1  A: 

In .NET the garbage collector will automatically free memory when an object can no longer be referenced from anywhere. When it does so, if the object has a finalizer it calls the finalizer. The finalizer is for cleaning up, usually unmanaged resources.

However, finalizers are expensive (they delay garbage collection on an object, for example) and you cannot tell when it will be run (as you can't tell when the GC will decide to collect it). They are usually left as a last resort for cleaning up things like unmanaged resources.

This is where the IDisposable interface and it's Dispose method comes in. Dispose can also be used to clean up, both managed and unmanaged resources. When you call the Dispose method it cleans up and the object is no longer in a stable, usable state.

If you have a resource which implements IDisposable you can call Dispose on it when you know you are done. That way and resources it is holding on to can be freed up as soon as possible. The usual way of doing this is to wrap it up in a using statement, which will automatically Dispose when the using block is done. e.g.:

using (SomeDisposableObject disposableObject = new SomeDisposableObject())
{
     disposableObject.DoSomeStuff();
     disposableObject.DoSomeMoreStuff();
}

When the using block is finished (after DoMoreStuff) Dispose is called on disposableObject. Using statements are a lot cleaner than the equivalent code when you take into account exception handling.

In the case of something like ToolTip, which has unmanaged references (a lot of WinForms in a wrapper around the unmanaged Win32 components) it will have a finalizer to make doubly sure the unamanged resources are freed correctly. However, if you call Dispose on the object, the cleanup code is run there and then and the finalizer is suppressed (it won't run when the object is collection by the GC).

So, to answer your question more directly, if you know exactly when an IDisposable is finished with it is a good idea to call Dispose. However, if you don't it is usually ok just to leave it up to the garbage collector to collect it and call the relevant code to correctly cleanup the object.

In the cases of ToolTip and Timer given, I wouldn't worry about calling Dispose on them yourself as I suspect it would be difficult to predict when they will be finished with.

ICR
That makes a lot of sense, unnecessary book keeping makes code complex and achieve few bytes reduction until the GC is called. But how to make sure that the object don't need to be disposed manually, people in other post saying you need to call Dispose on form related objects, as they have HWND, etc.
Priyank Bolia
Well if you can, call Dispose to clean HWND etc. up. However, if you don't the finalizer should clean it up for you. Not sure how that tallies with things like unexpected application exits etc. Hopefully someone more qualified can elaborate.
ICR