C#の「switch」とVBの「Select Case」の違い

先日、久しぶりにVBのソースをいじっていた時にC#の「switch」とVBの「Select Case」の仕様の違いに惑わされたので、備忘録として自分用にメモします。

C#の場合:フォールスルー禁止

C#の「switch」はフォールスルー禁止の仕様なので、明示的に「break;」しないとNGです。よって以下の記述はコンパイルエラーになります。

string productName = ""; 

switch (i)
{
    case 0:
        productName = "りんご";
        // break; がないのでコンパイルエラー

    case 1:
        productName = "ごりら";
        break;

    case 2:
        productName = "らっぱ";
        break;

    case 3:
        productName = "ぱんつ";
        break;

    default:
        productName = "つみき";
        break;
}

VBの場合:そもそもフォールスルーしない

対してVBの「Select Case」はフォールスルーしない仕様なので、以下の記述でOKです。

Dim productName As String  = ""

Select Case i

    Case 0
        productName = "りんご"

    Case 1
        productName = "ごりら"

    Case 2
        productName = "らっぱ"

    Case 3
        productName = "ぱんつ"

    Case Else
        productName = "つみき"

End select

複合条件の記述方法が変わってくる

この仕様の差異によって、複合条件の書き方が変わってきます。

C#は1つ1つのcaseで明示的に「break;」しないとフォールスルーする仕様なので、複合条件は以下のように記述します。

bool? isOdd = null;

for (int i = 0; i < 10; i++)
{
    switch (i)
    {
        case 1:
        case 3:
        case 5:
        case 7:
        case 9:
            isOdd = true;
            break;

        case 2:
        case 4:
        case 6:
        case 8:
            isOdd = false;
            break;
    }
}

VBは他のCaseにはフォールスルーしない仕様なので、以下のように記述します。

Dim isOdd As Boolean? = Nothing

For i As Integer = 0 To 9
    Select Case i

        Case 1, 3, 5, 7, 9:
            isOdd = True

        Case 2, 4, 6, 8:
            isOdd = False

    End  Select
Next

VBでC#チックに書いてもコンパイルエラーにならない

今回なんで戸惑ったかというと、VBはフォールスルーしないのに、C#のように書いてもコンパイルエラーにならないからです。

具体的に言うと、以下の記述でも仕様上は問題ないので、コンパイルエラーにはなりません。

Dim isOdd As Boolean? = Nothing

For i As Integer = 0 To 9
    Select Case i

        Case 1:
        Case 3:
        Case 5:
        Case 7:
        Case 9:
            isOdd = True

        Case 2:
        Case 4:
        Case 6:
        Case 8:
            isOdd = False

    End  Select
Next

しかし他のCaseにはフォールスルーしない仕様なので、iが1〜7の場合はisOddにTrueが設定されないし、2〜6の場合はFalseが設定されません。

これによって意図した結果にならず、ググるまでの数分間は悩んでしまいました。

どちらかと言うとC#の仕様の方が優秀

VBは勝手にフォールスルーをしないように制御されてしまう仕様なので、今回のケースが発生しました。

対してC#は意図的にフォールスルーできるし、明示的にフォールスルーしない記述をしなければコンパイルエラーになるので、今回のケースは発生しない仕様になっています。

大前提としてVBの仕様を忘れていた自分が悪いのはありますが、バグが発生しにくい仕様になっているC#の方が優秀だな、と今回のケースを通して思いました。

やっぱりC#たんかわいいよ。