Thursday 3 January 2008

C# Switch Fallthrough with goto

Everyone hates the thought of goto because it was so well abused back in the day. I've seen so many coding standards denying the use of the goto keyword due to the risk of introducing "spaghetti code". So let's make things very clear: I am not advocating the use of goto as a general control flow mechanism except in the very few cases where it's warranted. In other words, don't assume I'm a freak of nature simply because I've even mentioned goto in a positive light and it's not 1968.

As you're no doubt aware, C# is a modern programming language following in the tradition of C, C++, and JAVA. It's full of all the standard control flow operations like for, foreach, while, do...while, if, and switch and it also attempts to remove a number of trouble spots available with its ancestors (automatic fallthrough in switch statements, pointers, memory cleanup). So one must ask, then, why the language retains the lowly goto keyword! I've read examples of using goto in languages that don't support modern control flow constructs; in that context it makes perfect sense to overcome a deficiency of the programming language using the fundamentals provided. So how does it fit in today?

The behaviour of the switch statement in C# may not be what you're expecting if you're coming from a C background because case blocks don't "fall through" by excluding a break statement. Every C# case block must contain a break statement. This is a good thing because if you inadvertently forget a break statement in a language like C, the compiler may not warn you about the omission and case blocks will continue to execute until the switch statement ends or a break statement is reached. The end result: a defect--and potentially a very significant defect. In C# if you omit the break statement compilation will fail.

At first glance this sounds like the C# language doesn't allow fallthrough in a switch statement but that's only partly true: C# doesn't allow automatic fallthrough in a switch statement. If your design requires a case block fall through you can enable this behaviour explicitly using a goto statement. If you control yourself and don't run out and replace all of your existing control flow statements with gotos, you can even use a goto without feeling dirty all over.

I lied above when I said every C# case block must contain a break statement because you can optionally replace the break statement with a goto statement. If you write your goto statement to go to the next case statement, you achieve falthrough. Moreover, if your case statements are later reordered, your gotos will preserve the original fallthrough ordering unless the gotos are also updated--a bit of a pain but worth the extra safety.

Here are two examples switching on ints and strings:

switch (1)
{
case 1:
Console.WriteLine ("case 1");
goto case 2;
case 2:
Console.WriteLine ("case 2");
break;
default:
break;
}

switch ("hello")
{
case "hello":
Console.WriteLine ("case hello");
goto case "world";
case "world":
Console.WriteLine ("case world");
break;
default:
break;
}


4 comments:

  1. I use "goto" in switches to reduce code redundancies. Also wanted to point out that you can also end a case block with "return;" as this also prevents fallthrough by exiting the method.

    ReplyDelete
  2. goto statement is advisable for code maintainability. Use break. Or change the logic when you need a fall through.

    .Net Training

    ReplyDelete
    Replies
    1. goto statement is NOT advisable for code maintainability. Use break. Or change the logic when you need a fall through.

      Delete
  3. @prathap: switch statements are one of the simplest low-level control structures available in C# and not used enough imho; switch statements are one of the most effective means for clearly stating fall through situations to a maintenance programmer inheriting your code. You're just repeating the same old warning about gotos... goto is not always bad! The above examples are contrived and very simple but there's no reason why real world code (containing reams of daggy code and masking the case structure) can be refactored to be just as clear and concise.

    ReplyDelete

Spam comments will be deleted

Note: only a member of this blog may post a comment.