using statement on IDisposable object - delay of calling Dispose method

using (SomeDisposableResource resource = new SomeDisposableResource())
{
    // TODO: use the resource
}

is equivalent to:

SomeDisposableResource resource = new SomeDisposableResource();
try
{
    // TODO: use the resource
}
finally
{
    if (resource != null)
    {
        ((IDisposable)resource).Dispose();
    }
}

so, up to you to draw conclusions. Everything depends on how you define immediate. In a multithreaded environment other actions could be performed between the try block and the disposal of the resource but as it is wrapped in a finally block it is guaranteed that the Dispose method will be called.


I'm a little skeptical of that statement, and think they meant something else (perhaps garbage collection). A using statement is just syntactic sugar for a try/finally block where the finally block calls dispose. Given this C#:

using (var fs = new FileStream("C:\\blah.txt", FileMode.CreateNew))
{
    fs.WriteByte(7);
}

The IL looks like this:

//snipped
L_000e: nop 
L_000f: ldstr "C:\\blah.txt"
L_0014: ldc.i4.1 
L_0015: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string, valuetype [mscorlib]System.IO.FileMode)
L_001a: stloc.0 
L_001b: nop 
L_001c: ldloc.0 
L_001d: ldc.i4.7 
L_001e: callvirt instance void [mscorlib]System.IO.Stream::WriteByte(uint8)
L_0023: nop 
L_0024: nop 
L_0025: leave.s L_0037
L_0027: ldloc.0 
L_0028: ldnull 
L_0029: ceq 
L_002b: stloc.1 
L_002c: ldloc.1 
L_002d: brtrue.s L_0036
L_002f: ldloc.0 
L_0030: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_0035: nop 
L_0036: endfinally 
L_0037: nop 
L_0038: nop 
L_0039: ret 
.try L_001b to L_0027 finally handler L_0027 to L_0037

Notice on the last line it's just a .try and .finally. This is also indicated in The using statement from the C# spec.