1

I've been using Using lately but i wonder how it differs from calling .Dispose() explicitly. For instance what would be the difference between:

using (DisposableTest obj = new DisposableTest()) { /* Some code */ }

and

DisposableTest obj = new DisposableTest();
// Some code
obj.Dispose();

Assuming DisposableTest implements IDisposable ?

metalmad
  • 49
  • 1
  • 8
  • 1
    Question closed while answering with demonstration test codes. Duplicated topics cover your question with lots of answers and comments. Added my implementation to first one you can test it yourself – Saro Taşciyan Dec 29 '13 at 13:39

5 Answers5

6

The first version with the using keyword makes sure that obj is disposed even if the code in the middle throws an exception. It's like using a try finally block but less verbose.

Ganesh Sittampalam
  • 28,821
  • 4
  • 79
  • 98
6

They differ in a couple of ways:

  1. using creates a new scope.

  2. using calls .Dispose() regardless of how control leaves the block (if the object is not null at that point). It would be the same as writing a try/finally construct that places "if not null then .Dispose()" in the finally block, but in a format that expresses the intent.

It exists so that if control leaves the block in any way (an exception occurs or a return or break is encountered), the .Dispose() is still called. It is also more expressive because it better indicates the programmer's intent for this case than a generic try/finally construct.

Katsuyuki Omuro
  • 597
  • 3
  • 8
  • Thanks that was so detailed and well explained. Didn't think of `return` and `break` – metalmad Dec 29 '13 at 13:47
  • Updated the answer with a note on an implied null check. If the object provided to the `using` block is null at the time control leaves the block, it won't try to call `.Dispose()` on it. – Katsuyuki Omuro Dec 30 '13 at 04:57
4

From MSDN:

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

using (DisposableTest obj = new DisposableTest())
{
   // some code throwing exception here.
}

is equivalent to

{
   DisposableTest obj = new DisposableTest();
   try
   {
       // some code throwing exception here.
   }
   finally
   {
      obj.Dispose();
   }
}

Note the extra curly braces to create the limited scope for the object

Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
  • Hm, unless I'm reading this wrong, if the `DisposableTest` constructor throws an exception, `obj` will be null in the finalizer and Dispose will throw an exception. As far as I remember, `using` won't dispose objects where the _constructor_ throws an exception. I think the constructor call should be outside the `try` block. – Joachim Isaksson Dec 29 '13 at 13:18
  • @Joachim - Yeah that's true. I have updated the answer. Hope it makes sense now. – Rohit Vats Dec 29 '13 at 13:21
  • Your code sample with the `try`-`finally`-block does not compile, as `obj` has gone out of scope at the end of the `try`-block and thus is not visible in the `finally`-block. – O. R. Mapper Dec 29 '13 at 13:21
  • Rightly pointed out O.R.Mapper. Thanks.!! – Rohit Vats Dec 29 '13 at 13:24
  • @RohitVats Still, the constructor call should go _outside_ the try. If it throws an exception, the object should not be disposed. Only the code inside the `using` block should go inside the `try`. – Joachim Isaksson Dec 29 '13 at 13:27
4

There is absolutely no difference in your code. However, if the body of the block is non-empty, there would be a significant difference:

using (DisposableTest obj = new DisposableTest()) {
    <some code here> // This code may throw an exception
}

vs.

DisposableTest obj = new DisposableTest();
<some code here> // Same code as above
obj.Dispose();

If <some code here> throws an exception, the using block will execute obj.Dispose(), while the code without using will skip the call of obj.Dispose(). That is why one should prefer using in situations when ensuring the cleanup is critical.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

The difference is absent in fact. Using is more exceptions-safe: it does not skip execution, if it occurs. By the way, the third construction you can use is:

DisposableTest obj = null;
try
{
    obj = new DisposableTest();
}
catch(Exception e)
{
}
finally
{
    obj.Dispose();
}
Ilya Tereschuk
  • 1,204
  • 1
  • 9
  • 21