tags:

views:

339

answers:

6

I was reading another answer. And it made me wonder, when do does one need to explicitly call Dispose if I am using using statements?

EDIT:

Just to vindicate myself from being a total know-nothing, the reason I asked was because someone on another thread said something implying there was a good reason to have to call Dispose manually... So I figured, why not ask about it...?

+17  A: 

You don't. The using statement does it for you.


According to MSDN, this code example:

using (Font font1 = new Font("Arial", 10.0f)) 
{
    byte charset = font1.GdiCharSet;
}

is expanded, when compiled, to the following code (note the extra curly braces to create the limited scope for the object):

{
  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }
}

Note: As @timvw mentioned, if you chain methods or use object initializers in the using statement itself and an exception is thrown, the object won't be disposed. Which makes sense if you look at what it will be expanded to. For example:

using(var cat = new Cat().AsDog())
{
   // Pretend a cat is a dog
}

expands to

{
  var cat = new Cat().AsDog(); // Throws
  try
  {
    // Never reached
  }
  finally
  {
    if (cat != null)
      ((IDisposable)cat).Dispose();
  }
}    

AsDog will obviously throw an exception, since a cat can never be as awesome as a dog. The cat will then never be disposed of. Of course, some people may argue that cats should never be disposed of, but that's another discussion...

Anyways, just make sure that what you do using( here ) is safe and you are good to go. (Obviously, if the constructor fails, the object won't be created to begin with, so no need to dispose).

Svish
+1 . . . I'm not a cat person . . .
Binary Worrier
+5  A: 

Never. It will call Dispose once the statements inside using blocks finish execution.

shahkalpesh
+3  A: 

The whole point of the using statement is that if your object implements IDisposable, the dipose will be called at the end of the code block. That's what it's there for, to do it automaticaly for you.

Charles Graham
+12  A: 

Normally you don't. This is the point of the using statement. There is however a situation where you have to be careful:

If you reassign the variable to another value the using statement will only call the Dispose method on the original value.

using (someValue = new DisposableObject())
{
 someValue = someOtherValue;
}

The compiler will even give you a Warning about this:

Possibly incorrect assignment to local 'someValue' which is the argument to a using or lock statement. The Dispose call or unlocking will happen on the original value of the local.

Patrick Klug
+1 for mentioning the reassignment problem.
Dave Van den Eynde
I believe this warning is changed to an error in C# 3.5: "error CS1656: Cannot assign to 'someValue' because it is a 'using variable'"
Dathan
+3  A: 

As far as i know

using (var myDisposable = new MyDisposable())
{
   ...
}

is basically translated by the compiler to

var myDisposable = new MyDisposable()
try
{
   ...
}
finally
{
   myDisposable.Dispose();
}
Rauhotz
It also encloses the entire block in braces to limit the scope of myDisposable, and adds a check in the finally block to only execute Dispose() on non-null instances of myDisposable.
Dathan
+10  A: 

Be careful when using c# 3.0 object initializers though. An example can be found here: http://ayende.com/Blog/archive/2009/01/15/avoid-object-initializers-amp-the-using-statement.aspx

timvw
+1 Ouch, good point!
Dave Van den Eynde
+1 for a good counter the "never" responses
Alex Baranosky