Multiple variables in a using statement


Here’s a simple file copy program:

using System;
using
System.IO;

public class FileCopy
{
   
private static void Main(string
[] args)
    {
       
if
(args.Length != 2)
        {
           
Console.WriteLine("Usage: filecopy <source> <destination>"
);
           
return
;
        }

        Copy(args[0], args[1]);
    }

   
private static void Copy(string source, string
destination)
    {
       
const int
BufferSize = 64 * 1024;
       
using (FileStream input = File.OpenRead(source), output = File
.OpenWrite(destination))
        {
           
var buffer = new byte
[BufferSize];
           
int
bytesRead;
           
while ((bytesRead = input.Read(buffer, 0, BufferSize)) != 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }
    }
}

I’ve only recently learned that you can use multiple local variable declarators in the using statement, separated by comma, as long as they are of the same type. In the spec, section 8.13 (The using Statement), it says:

using-statement:

using ( resource-acquisition ) embedded-statement

resource-acquisition:

local-variable-declaration

expression

A using statement of the form

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

is precisely equivalent to a sequence of nested using statements:

using (ResourceType r1 = e1)

using (ResourceType r2 = e2)

using (ResourceType rN = eN)

statement

So we could rewrite our Copy method as follows:

    private static void Copy(string source, string destination)
    {
       
const int
BufferSize = 64 * 1024;
       
using (FileStream input = File
.OpenRead(source))
       
using (FileStream output = File
.OpenWrite(destination))
        {
           
var buffer = new byte
[BufferSize];
           
int
bytesRead;
           
while ((bytesRead = input.Read(buffer, 0, BufferSize)) != 0)
            {
                output.Write(buffer, 0, bytesRead);
            }
        }
    }

Note however that due to how local-variable-declaration is defined in the language spec, multiple variables have to be of the same type, and you only specify this type once at the beginning of the first declarator.


Comments (6)

  1. Jer0enH says:

    "as long as they are of the same type": this is a bit misleading, as you can simply declare the first variable to be of type IDisposable:

               using (IDisposable input = File.OpenRead(""), connection = new SqlConnection())

               {

               }

  2. Tommy Carlier says:

    @Jer0enH: if you declare them as IDisposable, then you can only call their Dispose-method. Or you'd have to cast them back to their original type (which defeats the point).

    I actually prefer splitting the usings in multiple lines. It's a lot more obvious and easier to read (1 line = 1 object created).

  3. Tom Toups says:

    What would be nice is if you could do something like the following:

    ResourceA a = new ResourceA();

    ResourceB b = new ResourceB();

    //ResourceA and ResourceB do not inherit from the same base, other than Object

    using (a,b)

    {

      //do stuff

    }

  4. Tommy – agreed. I didn't even know about this syntax until recently, but now it makes sense, given how it's defined in the grammar.

  5. Kundan says:

    Hey Kirill, the code samples posted above seem to be reversed. They need to be switched.

  6. Rob Simmermon says:

    This works because you have a nested using statement with technically one statement. Think of it like this:
    using(myVar = new something())
    {
    using(myvar2 = new something())
    {
    //now do stuff
    }
    }

    Since there is only one statement technically, you don’t need the curly braces.
    So the above is exactly the same as :

    using(myVar = new something())
    using(myvar2 = new something())
    {
    //now do stuff
    }

Skip to main content