Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've programmed in both C# and VB.NET for years, but primarily in VB. I'm making a career shift toward C# and, overall, I like C# better.

One issue I'm having, though, is curly brace soup. In VB, each structure keyword has a matching close keyword, for example:

Namespace ...
    Class ...
        Function ...
            For ...
                Using ...
                    If ...
                        ...
                    End If
                    If ...
                        ...
                    End If
                End Using
            Next
        End Function
    End Class
End Namespace

The same code written in C# ends up very hard to read:

namespace ... {
    class ... {
        function ... {
            for ... {
                using ... {
                    if ... {
                        ...
                    }
                    if ... {
                        ...
                    }
                }
            }
            // wait... what level is this?
        }
    }
}

Being so used to VB, I'm wondering if there's a technique employed by c-style programmers to improve readability and to ensure that your code ends up in the correct "block". The above example is relatively easy to read, but sometimes at the end of a piece of code I'll have 8 or more levels of curly braces, requiring me to scroll up several pages to figure out which brace ends the block I'm interested in.

share|improve this question
82  
I know this may sound preachy, and maybe you have special conditions that require it (because yeah, sometimes it's necessary - thankfully such times should be rare), but usually "...8 or more levels of curly braces, requiring me to scroll up several pages to figure out which brace ends the block I'm interested in" means the code needs some serious refactoring and cleanup. –  FrustratedWithFormsDesigner Nov 7 '12 at 15:40
7  
One thing I've seen done, and I've taken to doing, is at the end of a curly brace, I'll add a comment about it. Something like // End's using X statement. –  MyCodeSucks Nov 7 '12 at 15:41
13  
@FrustratedWithFormsDesigner is spot on about the fact that your control flow is a mess and needs to be redone. That said, I think you're complaining more about the curly braces than the scoping and I would say you just need to get used to it. Learning a language with significantly different syntax than you're used to definitely looks like soup for a bit of a while, but with practice that goes away. You just need to buckle down and deal until your brain starts to process the syntax more naturally, you'll get there. –  Jimmy Hoffa Nov 7 '12 at 15:42
2  
@FrustratedWithFormsDesigner - I need to cleanup a lot of COM objects in a COM interop situation. I'm using the technique suggested in this article: jake.ginnivan.net/vsto-com-interop. This easily creates two or three layers. When you stack the for loop, function, class and namespace on top of that (along with an if statement) you easily get to several layers of braces. –  JDB Nov 7 '12 at 15:44
3  
@TyrionLannister - And those can be some of the fastest comments to go out of sync with what they belong to... I think if I was going to have something like that, I'd prefer it to be auto-generated (at display-time only, not persisted) by the IDE. –  Clockwork-Muse Nov 7 '12 at 17:55
show 5 more comments

13 Answers

up vote 37 down vote accepted

Put your starting curly brace in the same "rank" as your ending one, like this:

namespace ... 
{
    class ... 
    {
        function ... 
        {
            for ... 
            {
                using ... 
                {
                    if ... 
                    {
                        ...
                    }
                    if ... 
                    {
                        ...
                    }
                }
            }
            // It's the `function` level!
        }
    }
}
share|improve this answer
15  
I agree. Egyptian brackets give me a headache. –  MyCodeSucks Nov 7 '12 at 15:42
8  
Also, most IDEs (probably) highlight a brace's partner when you click on it. –  StuperUser Nov 7 '12 at 15:45
3  
@TyrionLannister: Thanks for finally giving me a term for that style! I never had a good name for them other than "mis-aligned braces". –  FrustratedWithFormsDesigner Nov 7 '12 at 15:45
2  
@StuperUser - Hunting for the single highlighted character is what drove me to post this question in the first place. :) –  JDB Nov 7 '12 at 15:48
2  
@Cyborgx37: Does your IDE have a "Go to matching brace" feature? Usually bound to a key shortcut that automatically moves your cursor to the brace that matches the currently highlighted one. –  FrustratedWithFormsDesigner Nov 7 '12 at 15:49
show 8 more comments
  • Depending on your IDE: put your cursor at the open/close brace and it'll highlight both that and the corresponding brace.
  • Collapse the block and it shows you where it opens/closes.
  • Write smaller code blocks. Seriously. Check out Clean Code, and never run into this problem again (and have more readable/maintainable code).

One note, the following is valid c# syntax that might help your particular situation:

using (var type = new MyDisposable1())
using (var type2 = new MyDisposable2())
{
    /* do what you will with type2 and type2 */
}
share|improve this answer
    
Hunting for the single highlighted character is what drove me to post this question in the first place. –  JDB Nov 7 '12 at 15:48
2  
@Cyborgx37: Hence point 3. If your entire code block fits on screen, you never have to hunt. In most/all of the classes I write, the only pairs of braces that don't fit on screen are namespace/class. –  Steve Evers Nov 7 '12 at 15:50
    
What you suggest in points 1 & 2 is what I do now... but this requires that I leave the place where I'm coding and start manipulating my view of the code to figure out where to put the next line. Point 3 is well-taken, but not always possible, especially if your code requires several layers of using blocks (see jake.ginnivan.net/vsto-com-interop) –  JDB Nov 7 '12 at 16:12
    
@Cyborgx37: See my edit. –  Steve Evers Nov 7 '12 at 19:02
1  
@Cyborgx37 If you pick a color that stands out from everything else (I used purple background and white text for a while, IIRC) then there is no need to hunt for the matching brace - it practically SCREAMS at you "I'm HERE!". –  Michael Kjörling Nov 8 '12 at 9:20
add comment

A common convention is to add a comment after the closing brace to indicate the structure that it's closing:

if {
   ...
} // end if

while (condition) {
   ...
} // end while

etc. I've never warmed to this convention myself, but some people find it helpful.

share|improve this answer
15  
I have seen people do this, and when they swap/change the begining of the block (change a while to a for, swap to if statements) they almost NEVER remember to update the closing comments, rendering them worse than useless. This convention is probably only going to be useful if you can force yourself to maintain the comments every time the nature of the matching { changes. –  FrustratedWithFormsDesigner Nov 7 '12 at 15:44
    
Yeah, I've done some of this, but it's a lot of extra work (and noise). I was hoping there'd be something more straightforward. –  JDB Nov 7 '12 at 15:46
5  
Comments should only explain why never what or how as the code does both of those and relying on comments to explain either of them means the code is hard to read which is a sign the code should be corrected not commented. –  Jimmy Hoffa Nov 7 '12 at 15:51
1  
This makes me wonder why no one has written an editor that displays these comments, but doesn't actually include them in the code.. –  Brendan Long Nov 7 '12 at 23:34
2  
@JimmyHoffa: I think a better rule for comments is that they should provide clarity. Usually that means answering "why", but it can also mean other things. Don't get so caught up in dogma that it stops you from doing things that actually help, such as occasionally adding a comment to a closing brace that is far removed from its opening brace. –  Bryan Oakley Nov 8 '12 at 14:15
show 6 more comments

I think you need to tough it out with the braces. Eventually they will become second nature to you and you will be wondering how you ever lived without them.

Make sure they are indented appropriately though, and that some spacing convention is being followed (doesn't matter which).

share|improve this answer
    
A year later, and this advice rings true. :) –  JDB Dec 20 '13 at 18:33
add comment

In general, when it gets hard to match braces in whatever style - it probably means the method is too long and should be re-factored.

share|improve this answer
add comment

I remove 2 levels of nesting by collapsing the namespace and class scopes horizontally. Notice the methods are flush with the left edge of the screen. I don't see the point in losing 2 levels of indentation in every file.

After that it's rare you'll ever have nesting more than 4 levels deep.

namespace FooNameSpace {
class Foo {

public void bar()
{
    while(true)
    {
        while(true)
        {
            break;
        }
    }
}

public void fooBar()
{
    foreach(var item in FooList)
    {
        foreach(var b in item.Bars)
        {
            if(b.IsReady)
            {
                bar();
            }
            bar();
        }
        bar();
    }
}

}}//end class, namespace
share|improve this answer
    
I like this idea, but Visual Studio doesn't seem to support it (at least, 2008. We're upgrading to 2012 by the end of the year, so here's hoping) –  JDB Nov 8 '12 at 14:17
    
@Cyborgx37. I edit the text externally in VIM so it's not a problem. But in Visual Studio do: Control+A, then hit the "indent less" button. Only do it for new files. Don't bother with existing files as it will mess up the diff-comparisons in source control. –  mike30 Nov 8 '12 at 14:28
    
Typing in closing brackets/braces initiates an auto-format by VS but you can always hit CTRL+z to refuse its suggestion. –  Alex In Paris Nov 8 '12 at 14:36
add comment

I recently decided to try and formalize two rules about flow control constructs that basically go like this:

  • You should have nothing but necessary code-flow constructs
  • You should make the code-flow constructs as small as possible

For exactly the reasons you have mentioned and are clearly aware of, I think these are great rules to follow. There are a couple simple techniques you can employ to accomplish them:

  • Exit scope as soon as you can (this includes the scope of loops as well as functions)
  • Watch for elses that could be mitigated by exiting the function from the preceding if and apply the scope exiting technique as I mentioned
  • Reverse your conditional checks when the code inside an if is great than that outside
  • Factor code inside of a loop out to another method when the size of the loop grows to obscure the rest of the method
  • Watch for any scopes that only contain another scope, for instance a function whose entire scope is filled by an if with nothing outside of the if

I detailed here examples of how not following these can end up with you doing as you said and putting code in the wrong code block, which is bad and an easy cause of bugs cropping up during maintenance.

share|improve this answer
    
Thanks, there may be a block or two that I could refactor out. It will help, but it's hard to refactor out several nested using blocks. –  JDB Nov 7 '12 at 16:19
    
@Cyborgx37 actually using blocks can be inlined if they're nested fulfilling scopes, look here stackoverflow.com/questions/1329739/… it basically works like single line flow control constructs how you can if (true) doSomething(); you can also if (true) if (somethingElse) if (otherThings) { doThis(); doThat(); doWhatever(); } and the ifs nest as you expect (DON'T WRITE CODE LIKE THAT FOR THE LOVE OF GOD, JUST DO THIS WITH USINGS AND NOTHING ELSE heh) –  Jimmy Hoffa Nov 7 '12 at 16:25
    
Yes, I know about nesting using blocks, but this only works if you've got a single line underneath. In most of my code, that is not the case. Still a very helpful post overall... learned a few things (+1) –  JDB Nov 8 '12 at 14:19
    
@Cyborgx37 yeah I realize the scope nesting only works f you don't have extra bits, that said is there a pattern to the manner of your usings? Would it perhaps be viable to move some of that extra into the constructor if it's at the top or the disposal if it's at the bottom? That is if it's patterned; guessing it might be since you brought this up as an issue, so you probably run into these using nests often in your code. –  Jimmy Hoffa Nov 8 '12 at 15:37
    
I've actually started work on a Factory-pattern implementation which wraps COM objects in an "AutoCleanup" class. I then use a single using statement on the factory class and, when it is disposed, it automatically disposes all of the wrapped up classes. It's working well so far and has significantly reduced the number of using statements in my code. –  JDB Nov 8 '12 at 17:13
show 1 more comment

This is one of the oldest causes of warfare in computing, unfortunately. Reasonable arguments can be made from both sides (better vertical real-estate economy versus easier ability to visually match opening brace with closing brace), but in reality a simple source-code formatter will resolve everything for you. MS Visual C# has one built in that works well.

Be warned however that if you are working as part of a team you will be expected to conform to the conventions used by that team, so it pays to gain some familiarity with both styles and to refrain from getting religious over brace styles.

So while you're learning by all means focus on the style that makes it easier for you to learn, but keep half an eye on the other while you're at it and you'll do fine.

share|improve this answer
1  
I'm not sure if it's the default formatter or something in ReSharper, but when I used to use C# we had an option set that reformatted the code as part of the check-in. That way you could format the code however you wanted while you were working with it, but it would be reformatted to "project standard" on check-in. I think the only real formatting standard we had was to use spaces instead of tabs. –  TMN Nov 7 '12 at 16:15
add comment

There is an add-on to the editor that may help you at: C# Outline.

The add-on extends the VS20xx editor for C# by adding features to collapse, expand and highlight nested blocks of code. These features allows for easier editing and reading of nested contents of code blocks such as if, while, etc.

share|improve this answer
add comment

If you write your Code in Visual Studio, there's also a Plugin that shows you vertical dots between the beginning and the end of every structure that you construct.

But overall I think it'll just take some time until you're used to the "Curly-Braces-Soup". (Btw, I really like that expression. Sounds a bit like a Episode-Name for The Big Bang Theory)

share|improve this answer
add comment

Indentation tells you where you are, in both styles of syntax. If you write either a VB program or a C# program on a single line, you will soon not be able to tell where in the nested syntax you are. The machine parses the block ending phrases or curly braces, but humans need indentation.

Block ending phrases come from an era of punched cards and paper tape, when programming was much less interactive and visual. Or, really, not interactive at all. It was difficult to enter programs, and so programmers needed compilers to be very clever about syntax analysis and error recovery.

In that bygone era, the edit-compile-run cycle might have involved preparing punched cards with a card puncher, and then lining up to a job submission window where a clerk took the punched cards and submitted them to the machine. Later, the programmer would collect the output (printed on paper) from another window. If the program had errors, the output would consist of just the compiler diagnostics. When the turnaround times are long, the added cost of typing end if instead of just ) is justified if it helps to improve the quality of diagnostics, because the programmer needs to correct as many errors as possible in a single iteration to reduce the number of time-wasting iterations through the job submission window.

When a closing curly brace is missing, it is hard to tell which open brace is the one which is not closed. (The compiler may have to parse indentation to make an educated guess.) If you delete a closing brace inside a function, then it looks like the entire rest of the file is part of that function, resulting in a flurry of unhelpful error messages. Whereas if you have an end function syntax, the compiler can deduce where the erroneous function ends, recover, and parse the subsequent functions properly, giving you additional diagnostics, if any, which are meaningful.

When you're working in code-aware text editor which automatically indents and colorizes your code, on a high resolution screen where you can see sixty or more lines, the arguments for those kinds of clumsy languages no longer apply. You can incrementally edit and rebuild programs so fast that you can just deal with one error at a time. Moreover, by seeing large sections of the program simultaneously on the screen and maintaining proper indentation, you can reduce the occurrence of those kinds of nesting errors in the first place. And good programming text editor will even flag some kinds of syntax errors as you type. What is more, there are folding editors which will collapse the blocks of a program based on its syntax, giving an "outline-like" view of its structure.

Lisp used parentheses from the beginning and perhaps, not coincidentally, Lisp hackers pioneered programming as an interactive experience by building systems which accepted programs in small chunks (expressions).

In fact, you don't need ending symbols at all, as the Python language illustrates. The identation can just be the structure. Humans already use indentation to grok the structure of code even in languages where the machine relies on ending symbols or phrases.

share|improve this answer
add comment

Use Resharper, which will help recommend ways to reduce nesting. Also, read Bob Martin's book Clean Code, which emphasizes that a function should only do one thing, and therefore each function should only be a half-dozen lines long, so you won't have that many levels of nesting to worry about.

share|improve this answer
add comment

If you are using an IDE, Just press Crtl + k + D and the IDE will do the rest of the work.

share|improve this answer
    
which IDE eclipse uses ctrl-shift-i for indentation and ctrl-shift-f for formatting –  ratchet freak Nov 8 '12 at 11:01
    
check in visual studio –  Jagz W Nov 8 '12 at 12:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.