1

I wonder if the object created in the usingstatement gets disposed if I perform a return or throw operation. Example as follows.

using(SomeClass thing = new SomeClass())
{
  ...
  if(condition)
    return;
  ...
}

Will the above get confused or is GC to be trusted here?

Servy
  • 202,030
  • 26
  • 332
  • 449
Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438

7 Answers7

7

Yes, it will. The using statement will result in a finally block being created. A finally block's code will be run even if an exception is thrown in the related try block, or if there is a return statement in that try block.

There are only a few exceptions that can cause a finally block's code to not be executed, and they are all listed here, but my guess is that in your situation you'll be able to live with those consequences.

Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
2

using is the equivalent of try-finally so, yes, it does.

Peter Gluck
  • 8,168
  • 1
  • 38
  • 37
2

dispose if it is implemented will always get called. Its the equivalent of calling dispose in a finally block.

Gratzy
  • 9,164
  • 4
  • 30
  • 45
2

It will dispose, yes. It will create a finally block in the CIL code.

antonijn
  • 5,702
  • 2
  • 26
  • 33
2

Yes, because using is extended into a try finally by the compiler. The dispose will occur inside the finally block. Also, the finally will contain a test to check if the variables in the using are null (in case there are exceptions on the constructors).

lgoncalves
  • 2,040
  • 1
  • 14
  • 12
2

When writing a using statement:

using(SomeClass thing = new SomeClass())
{
    //...
    if (condition)
        return;
    //...
}

this will result in the following code:

SomeClass thing;
try
{
    thing = new SomeClass();
    //...
    if (condition)
        return;
    //...
}
finally
{
    if(thing != null)
    {
        thing.Dispose();
    }
}        

So all object declared using ( /* HERE */ ) will get disposed automatically. Objects declared inside the {} won't. But you can of course nest (or stack) using statements:

using (var thing = new SomeClass())
    using (var another = new Another())
        using (var somethingElse = new Whatever())
        {
            //...
        }

which in turn of course is just the syntactic sugar for writing

using (var thing = new SomeClass())
{
    using (var another = new Another())
    {
        using (var somethingElse = new Whatever())
        {
            //...
        }
    }
}

because when a statement is followed by just one block of code (in this case another using-block) you can skip the curly braces...

When using two or more objects of the same type you can chain the declaratio within the using-statement:

using (MemoryStream stream = new MemoryStream(), stream2 = new MemoryStream())
{
    //...
}

(Thanks to @Gratzy for pointing that out)

Spontifixus
  • 6,570
  • 9
  • 45
  • 63
1

For me, the question does not match with the details, and the details have been addressed here a bunch but not the title question...

Does using dispose all the the objects declared in it?

NO, it does not. It only calls Dispose() for the object(s) in its declaration. It does not call Dispose() for objects declared in it.

I usually see this kind of thing in code

using(var sqlConn = new SqlConnection("connStr"))
using(var sqlCmd = new SqlCmd("CmdText", sqlConn))
{
   sqlConn.Open();
   var reader = sqlCmd.ExecuteReader();
   while (reader.Read())
   {
     //stuff is done
   }
}

This will dispose and close both sqlConn and sqlCmd when the scope is complete for those but the reader that was declared in the using scope does not have Dispose() automatically called for it .

StingyJack
  • 19,041
  • 10
  • 63
  • 122
  • It's a great answer. Thanks. However, I wonder if you could elaborate on the mismatch between the message title and the details. I reread it and to me it appears obvious how they correlate. But it's **my** question so it might be more clear in **my** mind (filling some blanks ninja style) than in **yours**. I'll gladly alter the formulations if I only know what and how. – Konrad Viltersten Jul 16 '21 at 05:54
  • @KonradViltersten - The reader in my example is declared and instantiated inside the using block - "declared **in it**" as your title says. The rest of your question describes the variables that are **part** of the using statement declaration. This could be also be considered as "in it" but I dont because its not "inside it". HTH – StingyJack Jul 16 '21 at 15:43
  • Sorry, I had to deaccept your answer. Apparently, @servy feels that the edit doesn't comply with my original intention. Sorry to have caused commotion. – Konrad Viltersten Jul 16 '21 at 17:36
  • @KonradViltersten - no need to apologize to me for un-accepting the answer. Either interpretation could have been valid, I just wanted to make sure that both were represented here. – StingyJack Jul 16 '21 at 20:22