Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic function to handle disposing IDisposable objects

I am working on a class that deals with a lot of Sql objects - Connection, Command, DataAdapter, CommandBuilder, etc. There are multiple instances where we have code like this:

if( command != null )
{
    command.Dispose();
}

if( dataAdapter != null )
{
    dataAdapter.Dispose();
}

etc

I know this is fairly insufficient in terms of duplication, but it has started smelling. The reason why I think it smells is because in some instances the object is also set to null.

if( command != null )
{
    command.Dispose();
    command = null;
}

I would love to get rid of the duplication if possible. I have come up with this generic method to dispose of an object and set it to null.

private void DisposeObject<TDisposable>( ref TDisposable disposableObject )
    where TDisposable : class, IDisposable
{
    if( disposableObject != null )
    {
        disposableObject.Dispose();
        disposableObject = null;
    }
}

My questions are...

  1. Is this generic function a bad idea?
  2. Is it necessary to set the object to null?

EDIT:

I am aware of the using statement, however I cannot always use it because I have some member variables that need to persist longer than one call. For example the connection and transaction objects.

Thanks!

like image 463
Jerod Houghtelling Avatar asked Jul 06 '10 20:07

Jerod Houghtelling


People also ask

How do you Dispose of IDisposable?

If you don't use using , then it's up to you (the calling code) to dispose of your object by explicitely calling Dispose().

What is IDisposable interface in C implement the Dispose method?

IDisposable is an interface that contains only a single method i.e. Dispose(), for releasing unmanaged resources. IDisposable is defined in the System namespace. It provides a mechanism for releasing unmanaged resources.

What is the function of Dispose?

Dispose improves performance and optimizes memory by releasing unmanageable objects and scarce resources, like Graphics Device Interface (GDI) handles used in applications with restricted Windows space. The Dispose method, provided by the IDisposable interface, implements Dispose calls.

What happens if you dont Dispose IDisposable?

IDisposable is usually used when a class has some expensive or unmanaged resources allocated which need to be released after their usage. Not disposing an object can lead to memory leaks.


1 Answers

You should consider if you can use the using statement.

using (SqlCommand command = ...)
{
    // ...
}

This ensures that Dispose is called on the command object when control leaves the scope of the using. This has a number of advantages over writing the clean up code yourself as you have done:

  • It's more concise.
  • The variable will never be set to null - it is declared and initialized in one statement.
  • The variable goes out of scope when the object is disposed so you reduce the risk of accidentally trying to access a disposed resource.
  • It is exception safe.
  • If you nest using statements then the resources are naturally disposed in the correct order (the reverse order that they were created in).

Is it necessary to set the object to null?

It is not usually necessary to set variables to null when you have finished using them. The important thing is that you call Dispose when you have finished using the resource. If you use the above pattern, it is not only unnecessary to set the variable to null - it will give a compile error:

Cannot assign to 'c' because it is a 'using variable'

One thing to note is that using only works if an object is acquired and disposed in the same method call. You cannot use this pattern is if your resources need to stay alive for the duration of more than one method call. In this case you might want to make your class implement IDisposable and make sure the resources are cleaned up when your Dispose method is called. I this case you will need code like you have written. Setting variables to null is not wrong in this case but it is not important because the garbage collector will clean up the memory correctly anyway. The important thing is to make sure all the resources you own are disposed when your dispose method is called, and you are doing that.

A couple of implementation details:

  • You should ensure that if your Dispose is called twice that it does not throw an exception. Your utility function handles this case correctly.
  • You should ensure that the relevant methods on your object raise an ObjectDisposedException if your object has already been disposed.
like image 189
Mark Byers Avatar answered Oct 26 '22 18:10

Mark Byers