56

I was browsing a coworkers c# code today and found the following:

 using (MemoryStream data1 = new MemoryStream()) using (MemoryStream data2 = new MemoryStream()) { // Lots of code.......... } 

I had always seen the using statement followed by a pair of curly braces that defined the scope of the object life. My coworker who wrote the code said that the curly braces for the data1 using statement weren't needed and the code did the same thing as if they were present and nested the data2 using statement. So, what happens when the curly braces are ommitted?

5
  • 3
    Just my 2 cents - While you "can" do this, as demonstrated by the answers, I'm of the opinion that you shouldn't do it, for readability purposes. To me, it's just like wrapping the if/else/while/lock/etc. blocks in braces - even if they're not necessary, it's much easier to read. Commented Aug 17, 2010 at 21:54
  • 17
    In my opinion, stacked using statements, as above, are far more readable than nested using statements. Particularly in cases where you're chaining together 3-4 Streams/StreamReaders to perform a single set of operations. Commented Aug 17, 2010 at 22:36
  • 4
    @Joel: Maybe like anything else, the specific situation should be taken into consideration. If it was just two, my opinion is to absolutely nest them with braces. If we're talking 4 like you say, maybe stacked is the better approach. But the first time you need to access data1 prior to data2's creation, it means changing the readability of the code instead of just adding a line of code. Commented Aug 17, 2010 at 23:16
  • @Joe: Fair enough. In my experience, my usage of things involving using blocks tends to be rather cut and dried. I don't think I've ever had an occasion to insert some logic in between two stacked using statements, and I rarely have to modify them in any way once they're written. Commented Aug 18, 2010 at 17:56
  • I'm on team "no braces" or "use c#8 way without braces at all", but another idea might be to do all your nested usings and simply outsource the inner code to a method. Then it is very easy to read. using (var data1 ...) { using (var data2 ...) { using (var data3 ...) { MethodCall(data1, data2, data3); } } } Commented Aug 31, 2021 at 13:57

8 Answers 8

113

Yes, you can also put them in one using statement:

using (MemoryStream data1 = new MemoryStream(), data2 = new MemoryStream()) { // do stuff } 
Sign up to request clarification or add additional context in comments.

8 Comments

I'm pretty sure that the behaviour of this construct is different in certain cases. I don't remember exactly why right now, but I believe I read it in one of Bill Wagners books.
Note that you can only put multiple objects in a single using statement if they are all of the same type, MemoryStream in this case.
@fearofawhackplanet: There's no difference in behaviour according to the C# spec.
@fletcher: They're disposed in exactly the same order as standard nested using statements.
From the C# spec: "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"
|
27

From C# 8 you can also use this syntax without any braces:

using var foo = new Foo(); var bar = foo.Bar(); 

foo will then be disposed at end of its scope (usually at the end of a method) - so be mindful where & when to use.

Reference - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement#example

2 Comments

Just got caught out by this new syntax: I had a block of code which had one of these new "using"s in it and I refactored it out to a new method which returns the disposable object. Of course that caused a runtime error. If the braces had been there it would have been a clear indication as to the scope of the variable, and a warning that it wasn't a simple refactor.
I only learned about this new syntax yesterday from a YouTube video. I can't stop wondering why Microsoft didn't do this sooner.
22

The same rules apply when you omit the curly braces in a for or an if statement.

Incidentally if you reflect into the compiled code, the compiler decompiler adds the braces.

2 Comments

One difference is that, when nesting for statements, we would indent the inner one, but nested using statements are usually left-aligned. This is a matter of common convention, not language syntax, of course.
+1, nitpick point: The compiler does not actually add braces, the decompiler puts them in.
18

Exactly what he said. The code above is exactly the same as writing:

using (MemoryStream data1 = new MemoryStream()) { using (MemoryStream data2 = new MemoryStream()) { // Lots of code } } 

You can omit the curly braces after an if/else/for/while/using/etc statement as long as there is only one command within the statement. Examples:

// Equivalent! if (x==6) str = "x is 6"; if(x == 6) { str = "x is 6"; } // Equivalent! for (int x = 0; x < 10; ++x) z.doStuff(); for (int x = 0; x < 10; ++x) { z.doStuff(); } // NOT Equivalent! (The first one ONLY wraps the p = "bob";!) if (x == 5) p = "bob"; z.doStuff(); if (x == 5) { p = "bob"; z.doStuff(); } 

Comments

4

This is viable but risky, because if somebody later decides they want to do something to data1 before other stuff happens to it, they might place it right after the data1's using, which would take it out of the entire scope of data2's using. This would likely break compilation but still is a risky and pointless syntax shortcut..

2 Comments

That person should probably consider a different line of work.
@spoulson: true of so many people who don't, but it's still our jobs to keep the code as maintainable by others as possible, lest others put bugs in our code..
3

Exactly what your colleague said, that is the equivalent of nesting the statements. The dispose for data2 would be called immediately before the dispose function for data1.

Comments

2

As people have said: given there only being one line following a statement it will work without the curled braces. However, people are neglecting to show in their examples that that one line can be an if/using/for with it's own curled braces. Here is an example:

if(foo) if(bar) { doStuff(); } 

Comments

1

If there is only one instruction which follow the statement, the bracets are not needed. It is just like with if statement.

if(true) { Console.Writeline("hello") } 

means the same that

if(true) Console.Writeline("hello") 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.