web-dev-qa-db-ja.com

C#switchステートメントでの変数宣言

複数のケースで使用される変数のC#switchステートメントで、最初のケースでのみ宣言するのはなぜですか?

たとえば、次のエラーは、「 'variable'という名前のローカル変数はこのスコープで既に定義されています」というエラーをスローします。

switch (Type)
{
    case Type.A:
            string variable = "x";
                break;
    case Type.B:
            string variable = "y";
                break;
}

ただし、ロジックごとに、型がType.Bの場合、初期宣言はヒットしません。 switchステートメント内のすべての変数は単一のスコープ内に存在し、ロジックが処理される前に作成/割り当てられますか?

112
Jeremy

これは変数の全体的なスコープに関係していると思います。これはスイッチレベルで定義されるブロックレベルのスコープです。

個人的に、あなたの例でスイッチの内部の何かに値を設定して、それが本当に有益である場合、とにかくスイッチの外部でそれを宣言したいと思うでしょう。

42
Mitchel Sellers

特定のケースにスコープされた変数が必要な場合は、ケースを独自のブロックで囲むだけです。

switch (Type)
{
    case Type.A:
    {
        string variable = "x";
        /* Do other stuff with variable */
    }
    break;

    case Type.B:
    {
        string variable = "y";
        /* Do other stuff with variable */
    }
    break;
}
206
Michael Burr

はい、スコープはスイッチブロック全体です。残念ながら、IMOです。ただし、1つのケース内にいつでもブレースを追加して、より小さいスコープを作成できます。それらが作成/割り当てられているかどうかについて-スタックフレームには、メソッド内のすべてのローカル変数に十分なスペースがあります(キャプチャされた変数の複雑さは別として)。メソッドの実行中にスペースが割り当てられるわけではありません。

31
Jon Skeet

それらのスコープはswitchブロックにあるためです。 C#言語仕様 は次のことを示しています。

スイッチブロックで宣言されたローカル変数または定数のスコープは、スイッチブロックです。

10
itsmatt

変数はC#コンパイラのスコープを共有します。ただし、スコープは [〜#〜] cil [〜#〜] に同じようには存在しません。実際の作成/初期化については、変数が volatile としてマークされていない限り、.NETメモリモデルにより、単純なルールに従う限り、コンパイラは読み取り/書き込みを少し移動できます。

0
jezell