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#たんかわいいよ。