ここではC#のswitch文について理解しましょう。これはプログラムの基本構造で説明した選択にあたる処理です。
なお、プログラムの基本構造が分からない人は先に次の記事を読んでください。
プログラムの基本構造とは何でしょうか? これは特定のプログラミング言語に限らず、どの言語にも応用できる話です。内容は非常にシンプルで難しくありません。今後の助けになるので、ぜひ理解してください。 3つの基本構造 先に名前を出すと順次、選択、反復です。この3つの構造を使えば、どんなプログラムでも作れると言われてます。では、この3つは何を意味するのでしょうか。順番に解説していきます。 順次 (sequence) 最もシンプルな構造で、処理が上から下に進むことを...
switch statement (ステートメント)
if文と同じく条件分岐の処理になります。基本的にはif文と同じなのですが、switch文のほうが高度な記述ができます。
パターン1: switch 定数値
最もシンプルな記述はこれです。
評価値に記述できるのは数値や文字、文字列など、大抵の型は書けます。
また、caseは0個以上で好きなだけ記述できますが、defaultは0または1個だけです。
サンプルコードを用意してるので実行してみてください。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
Console.WriteLine("1");
break;
case 2:
Console.WriteLine("2");
break;
case 3:
Console.WriteLine("3");
break;
default:
Console.WriteLine("default");
break;
}
}
}
}
値に対して処理を分岐する場合はswitch文で記述したほうが美しいです。
また、caseの付近に書くのは:(コロン)なので注意してください。
パターン2: switch 条件式
なんと条件式も書けます。ちなみに定数値のcaseと併用も可能です。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 7;
switch (n)
{
case > 10:
Console.WriteLine("> 10");
break;
case > 5:
Console.WriteLine("> 5");
break;
case > 3:
Console.WriteLine("> 3");
break;
default:
Console.WriteLine("default");
break;
}
}
}
}
if文と違い、満たせない条件を下に書くとエラーでビルドできません。
次のサンプルコードはエラーの例です。試しにビルドを試みてください。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 7;
switch (n)
{
case > 1:
Console.WriteLine("> 1");
break;
case > 10:
Console.WriteLine("> 10");
break;
}
}
}
}
条件式はif文で書いたほうが分かりやすいので僕は使いません。
パターン3: switch 複数条件
複数の条件が1つのcaseを通るように記述できます。もちろん、defaultでも可能です。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
case 2:
case 3:
Console.WriteLine("1 or 2 or 3");
break;
default:
Console.WriteLine("default");
break;
}
}
}
}
このパターンは便利なので覚えておいたほうがいいですよ。
パターン4: Case guards (ケースガード)
あまり使いませんが紹介だけしておきます。条件式を書く時に複雑な条件だとcase式で書けない場合があります。
これは例を見たほうが早いのでサンプルコードを用意しました。whenで記述してる部分がポイントです。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int x = 10;
int y = 10;
switch ((x, y))
{
case ( > 0, > 0) when x == y:
Console.WriteLine("x == y");
break;
case ( > 0, > 0):
Console.WriteLine("x > 0 & y > 0");
break;
default:
Console.WriteLine("default");
break;
}
}
}
}
このようにwhenに追加の条件を記述することができます。ちなみに例のように複数の評価式を記述することも可能です。
ただし、このレベルになると理解しづらくなるので、無理にswitch文を使わずif文を使うほうが賢明でしょう。
スコープ
switch文の内部スコープは少し特殊です。
先に駄目な例を紹介するので、次のサンプルコードを確認してください。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
int x = 1;
break;
case 2:
int x = 1;
break;
}
}
}
}
どうですか? ビルドが通りませんよね。
これは複数のcase配下とdefault配下は同スコープで扱われるために、同名変数の定義エラーとなります。
では、どうするか。
最も簡単なのは上位で変数を宣言して使い回すことですが、スコープ範囲が増えるので良い記述ではありません。
これを解決する最も良い方法はcaseまたはdefaultの内部を{}で囲みブロック化します。そうすることで内部に新しいスコープを作ります。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
{
int x = 1;
break;
}
case 2:
{
int x = 1;
break;
}
}
}
}
}
同名の変数を作りたいことが多すぎて僕は常に{}で囲みます。と言うか仕様として元からスコープ分けてくれ。
fall through (フォールスルー)
C#では禁止されてますが内容は理解しておいてください。実はC言語など一部の言語には、フォールスルーと呼ばれる危険な仕様が存在します。
これはcaseの下にbreakを書かない記述法となり、何と次のcaseに処理が流れます。はっきり言ってバグの元でしかなく、禁止されるのも当然です。
仮にC#で書いた場合のサンプルコードです。case 1 を処理したら case 2 を処理、次に case 3 を処理って感じで全部通ります。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
Console.WriteLine("1");
case 2:
Console.WriteLine("2");
case 3:
Console.WriteLine("3");
break;
}
}
}
}
ちなみに複数個のcaseを並べるパターンがフォールスルーっぽく見えますが、あれは違います。
フォールスルーとは、case配下を実行して、さらに次のcase配下を実行する処理です。
相変わらずC言語やばい。
goto併用
先程のフォールスルーが禁止されてる理由は、breakの記述を忘れて意図しない動作になるからです。
つまりは自分の意志で明確に記述した場合、フォールスルーと同等の動きでも問題ないと言えます。
そんな願いを叶えてくれるのがgoto文です。次のように記述すると別のcaseまたはdefaultにジャンプできます。
namespace Sample
{
internal class Program
{
static void Main(string[] args)
{
int n = 1;
switch (n)
{
case 1:
Console.WriteLine("1");
goto case 2;
case 2:
Console.WriteLine("2");
goto case 3;
case 3:
Console.WriteLine("3");
goto default;
default:
Console.WriteLine("default");
break;
}
}
}
}
goto文は賛否両論な構文です。本来はswitch文に縛られず使う構文なので、これは別の機会で説明します。
ここでは最後のJump statementのgoto文について学びましょう。 goto statement (ステートメント) このgoto文とは、全ての制約を無視して指定したラベルまでジャンプ(移動)できるヤバい構文です。恐らく否定的な意見のほうが多く、僕もそうでしたが学校の授業なら100%使うなって教わります。 何故でしょうか? それはプログラムの基本構造を無視して動作するからです。では、実際にサンプルコードで動きを見てみましょう。 namespace Sam...
あとがき
昔はパターン1くらいしかなかったんだけど、気がついたら色々パターン増えてた。
◆ C#に関する学習コンテンツ
この記事は参考になりましたか?
コメント