switchにおけるフォールスルーの禁止

プログラミングC# 第6版 2.7.2


C#ではswitchにおけるフォールスルーがコンパイルエラーとなります。

using System;

class Program {
    static void Main() {
        int i = 0;
        switch(i) {
            case 0:
                Console.WriteLine("Hello, World0!");
                // breakの書き忘れ
            case 1:
                Console.WriteLine("Hello, World1!");
                break;
            default:
                Console.WriteLine("Hello, World!");
                break;
        }
    }
}
$ csc main.cs
Microsoft (R) Visual C# 2008 Compiler version 3.5.30729.1
for Microsoft (R) .NET Framework version 3.5
Copyright (C) Microsoft Corporation. All rights reserved.

main.cs(9,7): error CS0163: コントロールはひとつの case ラベル ('case 0:') から別のラベルへ流れ落ちることはできません。

これは便利ですね。C++ではbreakの書き忘れで思わぬバグを生んでしまうことがあるので注意が必要でした。

では逆にフォールスルーをしたい場合はどうしたらいいんでしょうか?

ズバリそれ用の処理があるんです。

using System;

class Program {
    static void Main() {
        int i = 0;
        switch(i) {
            case 0:
                Console.WriteLine("Hello, World0!");
                goto case 1; // 1へフォークスルーするよ
            case 1:
                Console.WriteLine("Hello, World1!");
                break;
            default:
                Console.WriteLine("Hello, World!");
                break;
        }
    }
}
$ main
Hello, World0!
Hello, World1!

goto case 1で0から1へ遷移していますね。素晴らしいです。

しかもgotoなので、直下だけでなく任意のケースに遷移できます。

using System;

class Program {
    static void Main() {
        int i = 0;
        switch(i) {
            case 0:
                Console.WriteLine("Hello, World0!");
                goto default; // defaultケースへ飛んでみる
            case 1:
                Console.WriteLine("Hello, World1!");
                break;
            default:
                Console.WriteLine("Hello, World!");
                break;
        }
    }
}
$ main
Hello, World0!
Hello, World!

うまくいってますね。

そして更にですね、caseに何も処理を書いてない場合はbreakを省略することが可能なようです。

using System;

class Program {
    static void Main() {
        int i = 0;
        switch(i) {
            case 0:
            case 1:
            case 2:
                // 上記ケースに何も処理が無い場合はbreakを省略してフォークスルーができる
                Console.WriteLine("Hello, World" + i + "!");
                break;
            default:
                Console.WriteLine("Hello, World!");
                break;
        }
    }
}
$ main
Hello, World0!

とても便利です。