-2

Possible Duplicate:
Variable declaration in c# switch statement
What is the purpose of the extra braces in Switch case?

Today I was writing a small piece of code and, at debugging time, VS slapped me and told me I made a big mistake with my local variables names: "A local variable named 'i' is already defined in this scope".

MyEnum enumerator = MyEnum.B;

switch (enumerator)
{
    case MyEnum.A:
        Int32 i = 0;
        // DoStuffsA();
        break;

    case MyEnum.B:
        Double i = 0D;
        // DoStuffsB();
        break;
}

So I said "Ok VS, let me fix it in a moment, I want to scope my cases first as I like them more!". So I made my cosmetic change... but suddenly VS stopped whining about that error:

MyEnum enumerator = MyEnum.B;

switch (enumerator)
{
    case MyEnum.A:
    {
        Int32 i = 0;
        // DoStuffsA();
        break;
    }

    case MyEnum.B:
    {
        Double i = 0D;
        // DoStuffsB();
        break;
    }
}

Ok... I'm aware of the meaning of "scope" and I know I produced two different scopes like so. The problem is that I don't know how switch statements are translated into IL code and I always thought that all the case statements were placed into the switch scope no matter if curly braces were used or not. So... the following oddity can be compiled, right?

MyEnum enumerator = MyEnum.B;

switch (enumerator)
{
    case MyEnum.A:
        String s = "Hello!";
        Console.WriteLine(s);
        break;

    case MyEnum.B:
        s = "Goodbye!";
        Console.WriteLine(s);
        break;
}

But not the following one:

MyEnum enumerator = MyEnum.B;

switch (enumerator)
{
    case MyEnum.A:
    {
        String s = "hello";
        Console.WriteLine(s);
        break;
    }

    case MyEnum.B:
    {
        s = "goodbye";
        Console.WriteLine(s);
        break;
    }
}

Can some explain me better the behavior of the compiler in this situation? Many thanks!

Community
  • 1
  • 1
Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98

3 Answers3

6

When you add the {} in the different case blocks, you are introducing scopes.

Without them, all case blocks are within one scope.

With your last two examples, where you use s - the first one is fine, as s is declared in the case for MyEnum.A so can be used in MyEnum.B, however with the braces, the declaration in MyEnum.A is in its own scope, not visible outside - so in MyEnum.B, s is not known and needs to be declared anew.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
5

Firstly, the translation to IL is somewhat irrelevant. IL doesn't have the same concepts of scope at all. This is all about the C# language specification.

It's pretty simple, really: the scope of a local variable is the block in which it's declared, and you can't declare one local variable when another local variable of the same name is in scope.

  • In your first snippet of code, the scope of i is the whole switch statement. Your second declaration tries to declare another i variable within the same scope, thus it fails.

  • In your second snippet of code, the scope of each i variable is just the block created by the curly braces - they're in entirely separate scopes, no nesting, so it's fine.

  • In your third snippet of code, the variable s is in scope for the second case, as its scope is the entire switch statement - so it's fine to use it.

  • In your fourth snippet of code, the variable s is only in the scope of the block in which it's declared (inside case A) so it's not in scope in case B.

I would strongly recommend against using code like your third snippet of code though. It will confuse many people. If you really want a variable which is in scope for multiple cases, I'd declare it before the switch statement.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
-1

Having the break inside the braces causes it to break to the end of the brace, at which point your case falls through. You need the break statement outside of the braces. E.g.

case MyEnum.A:
{
    String s = "hello";
    Console.WriteLine(s);
}
break;
Steve
  • 7,171
  • 2
  • 30
  • 52