Search code examples
c#scopeusingidisposableusing-statement

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


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?


Solution

  • 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.