tags:

views:

879

answers:

4

Since the C# using statement is just a syntactic sugar for try/finally{dispose} why does it accept multiple objects ONLY IF THEY ARE OF THE SAME TYPE?

I don't get it since all they need to be is IDisposable. If all of them implement IDisposable it should be fine but it isn't.

Specifically I am used to writing

using (var cmd = new SqlCommand())
{
    using (cmd.Connection)
    {
        // code
    }
}

which I compact into:

using (var cmd = new SqlCommand())
using (cmd.Connection)
{
    // code
}

and I would like to compact furthermore into:

using(var cmd = new SqlCommand(), var con = cmd.Connection)
{
    // code
}

but I can't. I could probably, some would say, write :

using((var cmd = new SqlCommand()).Connection)
{
    // code
}

since all I need to dispose is the connection and not the command but that's besides the point.

+4  A: 

Other variable declarations in C# only allow you to declare multiple variables of the same type in the same statement; I don't see why using headers should be different.

mquander
Yes and no. There's nothing stopping you from doing : IComparable c1, c2; and then later in your code have c1 and c2 be totally different concrete types that implement IComparable. That's what the OP is pointing out, all they need to be is IDisposable...
BFree
Sure, but you can do it in a using statement too with IDisposable, for example, this is legal: using (IDisposable a = new SqlCommand(), b = new SqlConnection())
mquander
BFree, that's exactly what mquander is saying, isn't it? using (IDisposable x = new Connection(), y = new Command()) would work but is rather useless. The type of the reference counts.
Henk Holterman
Ok, misread your answer. Got it now...
BFree
+1  A: 

I think this is actually a good idea. I would think it's just something that simply hasn't been implemented yet. I'd be surprised if there's an actual specific reason why this doesn't exist. I could be wrong though...

BFree
+2  A: 

You can do this though:

using (IDisposable cmd = new SqlCommand(), con = (cmd as SqlCommand).Connection)
{
   var command = (cmd as SqlCommand);
   var connection = (con as SqlConnection);
   //code
}

Perhaps that would be satisfactory to you.

Joseph
Looks nice, until you expand the //code line
Henk Holterman
@Henk I'm not following you.
Joseph
This is the closest workaround I've seen so far. However I'll need to cast the cmd back to SqlCommand in the block in order to manipulate it. The same with "con" which I'll have to open in order to do my job.
Andrei Rinea
@Andrei You're right, I'll update my answer to reflect what you're talking about.
Joseph
Which is exactly what I menat. I don't consider this an improvement over the using() using () { } version
Henk Holterman
Yeah, if you have to cast the stuff back later, it's absolutely worse than just putting it on two lines.
mquander
@Henk Oh I understand. I agree. I prefer to use the stacked usings myself as well. I was just giving an answer to his question of how you could do what he was trying to do.
Joseph
@Joseph, obviously this is a horrible technique as you have acknowledged, but it is certainly an ingenious piece of code to come up with!
RichardOD
+10  A: 

There's no particularly good technical reason; we could have come up with a syntax that allowed multiple declarations of nonhomogeneous types. Given that we did not, and there already is a perfectly good, clear, understandable and fairly concise mechanism for declaring nested using blocks of different types, we're unlikely to add a new syntactic sugar just to save a few keystrokes.

Eric Lippert
Oh I see... to protect us from syntactic diabetes we will not add any more syntactic sugar :P
Andrei Rinea
syntactic diabetes.. muahah :)
VVS