Home > database >  When is a `using var` disposed? Is it out-of-scope as soon as possible or at the end of the block?
When is a `using var` disposed? Is it out-of-scope as soon as possible or at the end of the block?

Time:01-05

https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/using#using-declaration

The lifetime of a using local will extend to the end of the scope in which it is declared. The using locals will then be disposed in the reverse order in which they are declared.

My question is: when is a using local considered out-of-scope?
Is it necessarily at the end of the block?
Is it necessarily right after its last use in the block?
Or is it implementation-defined, so that it could be either, or even anywhere in-between?

In other words:

{
  using var res = Res();
  res.DoStuff();
  somethingElse.DoWhatever();
  res.DoMoreStuff();
  // 100 more statements that have nothing to do with res
}

Is this always equivalent to this (1)?

{
  using (var res = Res()) {
    res.DoStuff();
    somethingElse.DoWhatever();
    res.DoMoreStuff();
    // 100 more statements that have nothing to do with res
  }
}

Or always to this (2)?

{
  using (var res = Res()) {
    res.DoStuff();
    somethingElse.DoWhatever();
    res.DoMoreStuff();
  }
  // 100 more statements that have nothing to do with res
}

Or is this an implementation detail?
Does the spec define this? What is such "scope" technically? If one of the above is always the case, is there a reason to prefer this behavior over the other? I'd assume (2) is better, but maybe I'm wrong.

I know it probably doesn't change much for high-level programming, but I'm curious.


Somewhat related: Does a using block guarantee that the object will not be disposed until the end of the block?

CodePudding user response:

This is what a Scope means according to the language spec:

The scope of a name is the region of program text within which it is possible to refer to the entity declared by the name without qualification of the name.

[...]

The scope of a local variable declared in a local_variable_declaration (§12.6.2) is the block in which the declaration occurs.

Note that a using declaration is just the word using added to a local variable declaration. According to the using declaration proposal,

The language will allow for using to be added to a local variable declaration.

Therefore, your using declaration is equivalent to

{
  using (var res = Res()) {
    res.DoStuff();
    somethingElse.DoWhatever();
    res.DoMoreStuff();
    // 100 more statements that have nothing to do with res
  }
}

The outermost { ... } denotes a Block.

CodePudding user response:

In the .NET Blog in Do more with patterns in C# 8.0 we can read:

Using declarations are simply local variable declarations with a using keyword in front, and their contents are disposed at the end of the current statement block.

And then we can see:

static void Main(string[] args)
{
    using var options = Parse(args);
    if (options["verbose"]) { WriteLine("Logging..."); }

} // options disposed here

CodePudding user response:

Also, about

The using locals will then be disposed in the reverse order in which they are declared.

using (var v1 = Class1()) // disposed third
using (var v2 = Class2()) // disposed second
using (var v3 = Class3()) // disposed first
{
  . . . .
}
  • Related