Disposal Order in C# Using Blocks
Asked Answered
J

2

8

I'm really bothered by having to nest using blocks in C#. It's not elegant and it takes up a lot of space. In some cases it appears to be unavoidable because I need to declare variables of different data types, but it seems like the single-type case should be possible to simplify. What I mean by "the single-type case" is when several variables of the same type are declared in series. Here's an example of what I'm talking about:

class Program
{
    static void Main(string[] args)
    {
        using (A a = new A("a"), b = new A("b"))
        {
        }
    }

    class A : IDisposable
    {
        string n = null;
        public A(string name)
        {
            n = name;
            Console.WriteLine(String.Format("Creating {0}", n));
        }

        public void Dispose()
        {
            Console.WriteLine(String.Format("Disposing {0}", n));
        }
    }
}

The way I want this to work is that a is constructed before b, and that b is disposed before a. Unfortunately there doesn't appear to be any direction in the C# specification as to how it should actually happen. It appears as though Microsoft's C# compiler treats it like this, as this is the output of running the above program:

Creating a
Creating b
Disposing b
Disposing a

However, I have no way of ensuring that this is deterministic behavior. Can someone either confirm or refute the idea that this sequence is deterministic? References would be great. And obviously, if it's prone to breakage (undocumented, etc.) it's probably not useful, but that's a good thing to know.

There's already a similar question about deterministic disposal that talks about the multiple-type case, and I understand that there's no real solution there aside from clever syntax tricks. Most of the answers there miss the point, anyway. My question is just about the single-type case and whether this disposal is deterministic and dependable or not. Thanks.

Jodhpur answered 10/8, 2010 at 13:43 Comment(1)
The alternative is uglier IMHOMcilwain
K
19

From the C# spec:

"A using statement of the form using (ResourceType r1 = e1, r2 = e2, ..., rN = eN) is precisely equivalent to a sequence of nested using statements:"

using (ResourceType r1 = e1)
   using (ResourceType r2 = e2)
      ...
         using (ResourceType rN = eN)
            statement

So it seems fair to say that this is quite set in stone.

Kerchief answered 10/8, 2010 at 13:47 Comment(2)
Cool, that's exactly what I needed to know. What section is that from, by the way? And what version of the spec? I did a full-text search of the C# 4.0 spec and still missed it.Jodhpur
I linked to the exact section :X msdn.microsoft.com/en-us/library/aa664736(v=VS.71).aspxKerchief
H
9

Is there any reason why you can't use the multiple-using trick? That is entirely deterministic, and solves your problem

using (A a = new A("a"))
using (A b = new A("b")) {
    // ....
}
Holcombe answered 10/8, 2010 at 13:46 Comment(1)
I don't like using that syntax for the same reason I don't like using 'if' statements without curly braces. It works, and I use it, but I'm always afraid that I'll break it during future maintenance. For mixed data types it's the only option, but it would be nice to have a cleaner deterministic syntax.Jodhpur

© 2022 - 2024 — McMap. All rights reserved.