8

Since C# uses Garbage Collection. When is it necessary to use .Dispose to free the memory?

I realize there are a few situations so I'll try to list the ones I can think of.

  1. If I close a Form that contains GUI type object, are those objects dereferenced and therefore will be collected?
  2. If I create a local object using new should I .Dispose of it before the method exits or just let the GC take care of it? What is good practice in this case?
  3. Are there any times in which forcing a GC is understandable?
  4. Are events collected by the GC when it's object is collected?
Neal
  • 599
  • 8
  • 16
  • possible duplicate of http://stackoverflow.com/questions/2714811/is-there-a-common-practice-how-to-make-freeing-memory-for-garbage-collector-easie – George Stocker Apr 27 '10 at 00:15
  • Also, duplicate of: http://stackoverflow.com/questions/331786/since-net-has-a-garbage-collector-why-do-we-need-finalizers-destructors-dispose See also: http://stackoverflow.com/questions/1090451/net-garbage-collector-basics http://stackoverflow.com/questions/1729289/net-garbage-collector-mystery http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage-collection-from-occuring http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage-collection-from-occuring http://stackoverflow.com/questions/888280/ http://stackoverflow.com/questions/371109/ – George Stocker Apr 27 '10 at 00:19
  • Generally IDisposable is implemented for unmanaged resources that won't be returned, closed or used optimally when the object is cleaned up by the GC - the managed object is always cleaned up by GC. See IDisposable @ http://msdn.microsoft.com/en-us/library/system.idisposable.aspx For #2, the GC takes care of the objects in managed code whether or not you call Dispose(). #1 and built-in "GUI type object"s will be collected whether you call Dispose() or not. Also see http://msdn.microsoft.com/en-us/magazine/bb985010.aspx – John K Apr 27 '10 at 00:23
  • 1
    @George: I don't think they are duplicate from any of those. I should perhaps clarify as my main question is when I should explicitly free memory and when should I not worry about it. The answer seems to be clear and that is, always Dispose of an object if it can be disposed is the preferred pattern. – Neal Apr 27 '10 at 00:26

5 Answers5

10

In theory, if you have properly defined componentry, it should never be required to call Dispose() on your objects, as the finalizer should eventually take care of it.

That being said, any time you're using an object that implements IDisposable, it's a good practice to call Dispose() on the object as soon as you are through working with it.

For some of your specific points:

1) If you know you're "done" with the Form, you can call Dispose() on it. This will force a cleanup at that point in time of the unmanaged resources associated with the form.

2) In this case: if your object is just used in that method, use "using" instead:

using (MyObject myObject = new MyObject())
{
   // use your object
} // It'll be disposed of here for you

3) There are rare reasons to do this, but in general, no.

4) Events are a delegate - the memory associated with the delegate will be collected after the delegate itself becomes unrooted, which typically happens when the objects in question are unrooted.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • I do use the using() {} pattern for all IO type resources. I'll start using it for all disposable object to follow a consistent pattern. Thanks for your answer. – Neal Apr 27 '10 at 00:31
3

You should call Dispose on every class that implements IDisposable. If it didn't need to be Dispose ed then it wouldn't implement IDisposable.

As for your other questions:

  1. When you add a control to the Form's Controls collection, then the control will be automatically disposed when the form is closed, so there's nothing you need to do there.
  2. If the object implements IDisposable, then you need to call Dispose. For example, if you go new FileStream(...), then the FileStream needs to be disposed, since it implements IDisposable. I would suggest you read up on the using construct in C# which makes it easier to handle IDisposable objects.
  3. Not really, 99.99% of the time, the garbage collector will know when the best time to run is. It's one of those, "you'll know when you need it" kind of situations.
  4. When the object containing the event is no longer referenced, then logically any object references contained in the event are also no longer referenced and will be available to be collected.
Dean Harding
  • 71,468
  • 13
  • 145
  • 180
  • #1: True but what if the object is added at design time but not added to the control's collection? Will it still be freed when the form is closed? #2: Indeed I almost always implement the using(){} pattern when dealing with IO resources. #4: I've read many instances where event not property removed will 'leak' memory. Or rather not release the memory. I realize this may only be a reference which is negligible. – Neal Apr 27 '10 at 00:36
  • On #4, when the object *containing* the event is no longer references, an object references the event itself holds will also no longer be referenced. The problem comes when you add a handler to an event, the event holds a reference to that object: so the object will not be reclaimed until the *event* is reclaimed or you manually unsubscribe. For most WinForms stuff, the event handler is usually in the containing form anyway so it's usually not an issue. – Dean Harding Apr 27 '10 at 04:07
2

Look at this question:

Is there a common practice how to make freeing memory for Garbage Collector easier in .NET?

If your class instantiates the IDisposable interface, that (probably) means that it has system resources that have to be disposed of directly. One easy way to accomplish that is to use the using keyword, as in:

using(var g = Graphics.FromBitmap(bmp))
{
    //Do some stuff with the graphics object
}

per @Matt S's answer in that question I referenced.

For your questions:

  1. If you instantiate an object that has IDisposable, you will need to dispose it when you close the form. That's tricky in WPF and straightforward in Winforms, since winforms dialogs have Dispose methods. For WPF, I've solved the problem by keeping the WPF class around but hidden, called a dispose method that disposes all objects (like serial ports), and then sets the WPF class to null.
  2. No. Let the GC take care of it.
  3. I think so, but I got dinged with negative votes :) When I've done very large allocations, forcing GC to remove them is, imo, a good idea.
  4. I'm not sure. I think that events are, in and of themselves, objects, so will get collected when no longer used.
Community
  • 1
  • 1
mmr
  • 14,781
  • 29
  • 95
  • 145
  • your #2 response seems to conflict everyone else answer. Why would you say let the GC take care of it? Also it seems to conflict somewhat with your original statement? – Neal Apr 27 '10 at 00:32
  • If you just make an object using new, but it does not implement the IDisposable interface, let the GC take care of it. But, if it implements IDisposable, then you must dispose of it before you let it go, as per #1. If you declare a new array of ints, int does not implement IDisposable, so you can let the gc take care of it. – mmr Apr 27 '10 at 00:44
1

Like Reed Copsey said, it's usually not necessary to call Dispose.

A possible case that may be creating your problem is that a static object is holding references of other objects that are no longer used anywhere else. The following code shows an example:

Form_Load(...)
    MyState.Instance.AddressChanged += this.User_AddressChanged;
End

If for some reason, when form is unloaded, the code does not unregister the event handler, the form instance will still be referenced by the state object.

Codism
  • 5,928
  • 6
  • 28
  • 29
0

If you are using an IDisposable object, consider using the using statement to automatically deal with the disposing for you.

hzap
  • 1,103
  • 7
  • 9