views:

777

answers:

13

What resources have to be manually cleaned up in C#? ...and what are the consquences of not doing so?

For example, say i have the following code:

myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black);
//Use Brush

If i don't clean up the brush using the dispose method, i'm assuming the garbage collector frees the memory used at program termination? Is this correct?

What other resources do i need to manually clean up?

+6  A: 
  • Handles to internal windows data structures.
  • Database connections.
  • File handles.
  • Network connections.
  • COM/OLE references.

The list goes on.

It's important to call Dispose or even better yet, use the using pattern.

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}


If you don't dispose something, it'll be cleaned up when the garbage collector notices that there are no more references to it, which may be after some time.

In the case of System.Drawing.Brush, Windows will keep internal windows structures for the brush loaded in memory until all programs release their handle.

Orion Adrian
+2  A: 

Generally, anything that implements IDisposable should cause you to pause and research the resource you're using.

GC only happens when there's memory pressure, so you cannot predict when. Although an unload of the AppDomain will certainly trigger it.

Brett Veenstra
A: 

The garbage collector will handle any managed resources. In your example, the brush will be cleaned up when the garbage collector decides to, which will happen some time after the last reference to the brush is no longer valid.

There are certain things that need to be manually cleaned up, but those are pointers retrieved from unmanaged sources, such as DLL calls, nothing within the .NET Framework needs this treatment however.

Guvante
This answer was meant to explain when you _need_ to clean up your resources, not when you should, as others did. From the tone of the original question I assumed this was what was wanted.
Guvante
A: 

Well, as long as you use the managed version of the resources and don't call the windows APIs by yourself, you should be OK. Only worry about having to delete/destroy a resource when what you get is an IntPtr, as "windows handles" (and a whole lot other things) are known in .NET, and not an object.

By the way, the resource (as any other .NET object) will be flagged for collection as soon as you leave the current context, so if you create the Brush inside a method, it will be flagged when you exit it.

dguaraglia
+6  A: 

If you don't dispose something, it'll be cleaned up when the garbage collector notices that there are no more references to it in your code, which may be after some time. For something like that, it doesn't really matter, but for an open file it probably does.

In general, if something has a Dispose method, you should call it when you've finished with it, or, if you can, wrap it up in a using statement:

using (SolidBrush myBrush = new System.Drawing.SolidBrush(System.Drawing.Color.Black))
{
    // use myBrush
}
Khoth
A: 

If it's managed (i.e. part of the framework) you don't need to worry about it. If it implements IDisposable just wrap it in a using block.

If you want to use unmanaged resources then you need to read up on finalisers and implementing IDisposable yourself.

There's a lot more detail under this question

Keith
+1  A: 

Technically anything that inherits from IDisposable should be proactively disposed. You can use the 'using' statement to make things easier.

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

Sometimes you will see inconsistent use of IDisposable derived objects in documentation sample code as well as code that is generated by tools (i.e. visual studio).

What's nice about IDisposable is that it gives you the ability to proactively release the underlying unmanaged resource. Sometimes you really want to do this - think network connections and file resources for example.

Eric Tobia
A: 

Hi First upon program termination, you can assume that memory used by the process will be eliminated with the process itself.

While using dispose or destructor in.net, one must understand that the time of when the dispose function is called by the GC is non-deterministic. That why it is recommended to use the using or calling the dispose explicitly.

When using resources such as files, memory objects such as semaphors and resources that live outside of the managed world of .net must be freed.

The SolidBrush for example, you need to dispose because it is a GDI object and living outside of the .net world.

ArielBH
A: 

The garbage collector does not only free up at program termination, otherwise it would not be really useful (on any decent/recent OS, when the process exits, all its memory is cleaned up automatically by the OS anyway).

One of the big advantage of C# compared to C/C++ is that you don't have to care about freeing allocated objects (most of the time at least); the gc does it when the runtime decides (various strategies when/how to do it).

Many ressources are not taken care of by the gc: file, thread-related ressources (locks), network connections, etc...

David Cournapeau
+3  A: 

The consequences of not disposing your IDisposables can vary from a negligible performance hit to crashing your app.

The Brush object in your example will be cleaned up by the GC when it feels like it. But your program won't have had the benefit of that bit of extra memory you would have gained by cleaning it up earlier. If you are using a lot of Brush objects this might become significant. The GC is also more efficient at cleaning up objects if they haven't been around very long, because it is a generational garbage collector.

On the other hand, the consequences of not disposing database connection objects could mean you run out of pooled database connections very quickly and cause your app to crash.

Either use

using (new DisposableThing...
{
    ...
}

Or, if you need to hold on to a reference to an IDisposable in your object for its lifetime, implement IDisposable on your object and call the IDisposable's Dispose method.

class MyClass : IDisposable
{
    private IDisposable disposableThing;

    public void DoStuffThatRequiresHavingAReferenceToDisposableThing() { ... }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    //etc... (see IDisposable on msdn)

}

Matt Howells
A: 

One place to be careful is Objects that look small to GC but are not... In the SharePoint API for example, the SPWeb object has a small footprint as far as the GC is concerned and so will have low priority for collection, but it has really grabbed a bunch of memory (in the heap I believe) that the GC doesn't know about. You will run into some fun memory issues if you are foreaching a whole bunch of these for example, always remember to use using or dispose!

spdevsolutions
+1  A: 

As others have said, using is your friend. I wrote this blog entry about how to implement IDisposable in a fairly straightforward way that is less error-prone by factoring out the parts that are the most important.

plinth
+1  A: 

A trick I use when I can't remember whether a given object is a disposable resource is to type ".Dispose" (at most!) after the declaration to get Intellisense to check for me:

MemoryStream ms = new MemoryStream().Dispose

Then delete the .Dispose and use the using() directive:

using(MemoryStream ms = new MemoryStream())
{
  ...
}
Note that this trick won't work if Dispose has been implemented explicitly!
Rasmus Faber