7

After recently encountering this while programming, I have been wondering about this. Below are 2 snippets which are both legal and compile. Specifically, my question is this.. in the second case, do the brackets make the program slower? Also why is this allowed?

1st case:

if (statement)
{
 // do something
}

2nd case:

{
    if (statement)
    {
        // do something
    }
}

Additionally what if I had something like the code below.. Is the runtime the same as just calling function X without any of the curly brackets.

{
  {
    {
      // call function X
    }
  }
}
Michael Geary
  • 28,450
  • 9
  • 65
  • 75
sparta93
  • 3,684
  • 5
  • 32
  • 63
  • 3
    No they are just used for grouping. Also this question is off topic on here. – deathismyfriend Jul 14 '15 at 16:57
  • 3
    Technically they are scopes but I would assume the compiler is smart enough to remove the unnecessary scopes. – MiltoxBeyond Jul 14 '15 at 16:58
  • 1
    Adding additional curly braces in unlikely to make the program slower, because they are used to specify scope. This question has been discussed [here](http://stackoverflow.com/questions/6136853/why-does-c-sharp-allow-code-blocks-without-a-preceding-statement). – Matt Martin Jul 14 '15 at 17:02
  • @deathismyfriend - The [Stack Overflow guidelines](http://stackoverflow.com/help/on-topic) seem to indicate that this question is on topic: "a practical, answerable problem that is unique to software development." Also, see [Jon Skeet's answer](http://stackoverflow.com/a/31413664/1202830) for an interesting case where extra braces can affect performance. – Michael Geary Jul 14 '15 at 18:12
  • @MichaelGeary This is a performance / code optimization question. In which case it should be on Code Review not on stack overflow. – deathismyfriend Jul 14 '15 at 18:14
  • 4
    @deathismyfriend This would be off-topic on Code Review as stub code. If the OP wishes for a code review, they are welcome to post the full code they would like reviewed.. The basic guidelines are: (a) the code works as intended, (b) the code is real code, rather than example code, and (c) the code is included in the body of the question. – Phrancis Jul 14 '15 at 18:18
  • @deathismyfriend - There are over 50,000 questions on those topics in the [performance](http://stackoverflow.com/?tags=performance) and [optimization](http://stackoverflow.com/?tags=optimization) tags. – Michael Geary Jul 14 '15 at 19:31

7 Answers7

13

Most of the time it doesn't make any difference - and you should definitely code for readability more than anything else.

However, curly braces can have an effect on performance, in a surprising way, although it's pretty unusual. Consider this code:

using System;
using System.Collections.Generic;

class Test
{
    static void FewerCurlies()
    {
        List<Action> actions = new List<Action>();
        for (int i = 0; i < 100; i++)
        {
            int x;
            if (i % 3 == 0)
            {
                actions.Add(() => x = 10);
            }

            int y;
            if (i % 3 == 1)
            {
                actions.Add(() => y = 10);
            }
        }
    }

    static void MoreCurlies()
    {
        List<Action> actions = new List<Action>();
        for (int i = 0; i < 100; i++)
        {
            {
                int x;
                if (i % 3 == 0)
                {
                    actions.Add(() => x = 10);
                }
            }

            {
                int y;
                if (i % 3 == 1)
                {
                    actions.Add(() => y = 10);
                }
            }
        }
    }
}

The extra braces in MoreCurlies look redundant, right? Not quite... the generated code looks more like this:

using System;
using System.Collections.Generic;

class Test
{
    static void FewerCurlies()
    {
        List<Action> actions = new List<Action>();
        for (int i = 0; i < 100; i++)
        {
            FewerCurliesCapture capture = new FewerCurliesCapture();
            if (i % 3 == 0)
            {
                actions.Add(capture.Method1);
            }

            if (i % 3 == 1)
            {
                actions.Add(capture.Method2);
            }
        }
    }

    static void MoreCurlies()
    {
        List<Action> actions = new List<Action>();
        for (int i = 0; i < 100; i++)
        {
            {
                MoreCurliesCapture1 capture = new MoreCurliesCapture1();
                if (i % 3 == 0)
                {
                    actions.Add(capture.Method);
                }
            }

            {
                MoreCurliesCapture1 capture = new MoreCurliesCapture2();
                if (i % 3 == 1)
                {
                    actions.Add(capture.Method);
                }
            }
        }
    }

    private class FewerCurliesCapture
    {
        public int x;
        public int y;

        public void Method1()
        {
            x = 10;
        }

        public void Method2()
        {
            y = 10;
        }
    }

    private class MoreCurliesCapture1
    {
        public int x;

        public void Method()
        {
            x = 10;
        }
    }

    private class MoreCurliesCapture2
    {
        public int y;

        public void Method()
        {
            y = 10;
        }
    }
}

The differences here are:

  • An instance of the capture class is created in each iteration of the loop in FewerCurlies, even if it's not used
  • Each instance of the capture class used in FewerCurlies contains both variables, even though each delegate will only actually use one of them, whereas in MoreCurlies each capture class only captures a single variable

This is all somewhat implementation-specific, but it shows that redundant-looking curlies can have an impact.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • What is the logic of putting the capture variable in the for-block in the `FewerCurliesCapture`? Why not inside the `if` block? How come the compiler is smart enough to see that it is enough to use one capture class in the `FewerCurlies` example, but not in the `MoreCurlies` example? – Simon Forsberg Jul 14 '15 at 18:27
  • @SimonAndréForsberg: You could indeed put it in the `if` - I was just demonstrating the difference that scope can make. I'd argue that the compiler was smarter in the `MoreCurlies` case - having two smaller capture classes is better than one big one, in this case. But basically the compiler ends up with one capture class per scope, which captures all the captured variables from that scope. At least, that's what the current implementation does... – Jon Skeet Jul 14 '15 at 18:29
  • For further discussion by Jon Skeet and Eric Lippert, see [SO: Discrete Anonymous methods sharing a class?](http://stackoverflow.com/q/3885106/18192) – Brian Jul 14 '15 at 19:32
4

Short answer is "no, they do not reduce performance".

Curly braces are needed for the compiler to determine scope of variables, and to know where the current group of statements end. Once the compiler finished processing, the code with and without the unnecessary curly braces would produce identical output.

Note that this is related to the performance of compiled code, not to the performance of the compiler itself. The compiler will take additional time to compile your code, simply because the raw size of the input is larger. However, in order for this additional time to become measurable, the number of unnecessary braces needs to be rather extreme.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    "Once the compiler finished processing, the code with and without the unnecessary curly braces would produce identical output." It would in this case. In some cases it can make a difference in terms of captured variables though. – Jon Skeet Jul 14 '15 at 17:16
  • @JonSkeet, I'm not sure that's true. Please see my answer. I tried putting the variable at a different scope to where it's modified and then returned, but the IL was still identical. – David Arno Jul 14 '15 at 17:29
  • @DavidArno: It *is* true, but only when you're capturing variables, which your code doesn't... and even then it would depend on exactly what you're doing. – Jon Skeet Jul 14 '15 at 17:30
  • @JonSkeet I meant purely redundant braces, similar to what OP has in his examples. – Sergey Kalinichenko Jul 14 '15 at 17:31
  • @dasblinkenlight: They can still be purely redundant in terms of visible effect. Will add an example. – Jon Skeet Jul 14 '15 at 17:34
  • @JonSkeet, ah fair point. I tried it with a closure and `X` ended up larger when compiled.. – David Arno Jul 14 '15 at 17:35
  • @DavidArno: See my answer for a long example of how it works :) – Jon Skeet Jul 14 '15 at 17:42
  • @JonSkeet In your example the braces only look redundant, but they are not, because they let you do something you couldn't do without them. Specifically, `MoreCurlies` can replace `int y` with `int x`, while `FewerCurlies` cannot do the same thing. – Sergey Kalinichenko Jul 14 '15 at 17:55
  • @dasblinkenlight: Agreed - but they don't affect the observable behaviour of the code that *is* there. One could argue that the curlies around a single-statement `if` body aren't redundant, because they let you add an extra statement... you'd have to define "purely redundant" *really* carefully. (I think there are other kinds of "introducing new scope" braces which look redundant but make a difference to valid code in C# 5 due to some rules which were then changed in C# 6, too...) – Jon Skeet Jul 14 '15 at 17:57
4

As ever with such questions, the answer lies in the IL it generates. For the following code examples:

public int X()
{
    {
        {
            {
                return 0;
            }
        }
    }
}

public int Y()
{
    return 0;
}

We end up with the following compiled IL:

.method public hidebysig instance int32  X() cil managed
{
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  ldc.i4.0
  IL_0001:  ret
} // end of method SomeType::X

.method public hidebysig instance int32  Y() cil managed
{
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  ldc.i4.0
  IL_0001:  ret
} // end of method SomeType::Y

They are identical. so no, it has no affect on performance. X is horrible to read, but that's another issue.

Update {} affects the scope of variables, so perhaps this could have an effect. Again, let's check:

public int X()
{
    var i = 1;
    {
        {
            i++;
            {
                return i;
            }
        }
    }
}

public int Y()
{
    var i = 1;
    i++;
    return i;
}

Once again though, the IL produced is identical:

// Code size       8 (0x8)
.maxstack  2
.locals init ([0] int32 i)
IL_0000:  ldc.i4.1
IL_0001:  stloc.0
IL_0002:  ldloc.0
IL_0003:  ldc.i4.1
IL_0004:  add
IL_0005:  stloc.0
IL_0006:  ldloc.0
IL_0007:  ret

However if the variable is captured in a closure, it does affect things. X in the following case does create more IL, which would have an impact on performance:

public Func<int> X()
{
    {
        var i = 1;
        {
            i++;
            {
                return () => i;
            }
        }
    }
}

public Func<int> Y()
{
    var i = 1;
    i++;
    return () => i;
}
David Arno
  • 42,717
  • 16
  • 86
  • 131
  • In .NET 4.5 the same IL code is produced for methods `X` and `Y` from the last snippet. – Kapol Jul 21 '15 at 07:28
2

Unlike C++, in which the compiler may be required to generate code when variables go into or out of scope, most variables in C# are effectively hoisted to the enclosing function-level scope. The code:

void foo()
{
  {
    int i;
    ... stuff using i as int
  }
  {
    char i;
    ... stuff using i as char
  }
}

will effectively get turned into:

void foo()
{
  int i__1;
  char i__2;
  ... stuff using i__1 as int
  ... stuff using i__2 as char
}

with code from the first braced section using the first variable i__1 wherever it would have used i, and code in the second one using i__2. In some cases it is possible that declaring variables with the same name and purpose within multiple scoping blocks might generate less efficient code than declaring one variable with that common purpose in an outer scoping block, but it would rarely have a meaningful effect. In most cases the just-in-time compiler will be able to determine that multiple variables in the code can safely be mapped to the same storage location, and even in those where it can't the storage required for a few extra variables is unlikely to affect performance very much.

supercat
  • 77,689
  • 9
  • 166
  • 211
1

No curly braces not going to reduce performance.

Something its helpful to understnad code and provide good formating of code. But some curly braces are mandatory like function start /end,loop start/end,condition start/end and this barces also help to understand scrop of variables.

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
0

Its doesn't Cause any performance degradation but using curly brackets definitely increases the readability of your code. In real word scenario when you have peer code reviews or pair programming then the stuffs written by you would be much clear and readable.

Go through the following link

http://www.c-sharpcorner.com/UploadFile/d0e913/lame-question-of-the-day-role-of-curly-braces-in-our-cod/

Anamay
  • 71
  • 1
  • 2
  • 10
0

Using unnecessary curly braces, assuming you have no nested variables, only adds a label to the label table during while it's converting your code to byte-code or machine code. So at worse the build time will be slower. If you have variables in the nesting you still shouldn't have problems if they are primitives which don't have destruction code but if you have objects created within the nested braces then a stronger understanding of the GC would be required, but I strongly doubt that any noticeable difference would be present. In all cases because the compiler is doing extra work by storing references in a lookup table while it builds your project, then there will be a, although probably unnoticeable, slight delay in building your project.

ydobonebi
  • 240
  • 2
  • 11