私はかなり長い間 C# を使ってきましたが、以下のことには気づきませんでした。
public static void Main()
{
for (int i = 0; i < 5; i++)
{
}
int i = 4; //cannot declare as 'i' is declared in child scope
int A = i; //cannot assign as 'i' does not exist in this context
}
では、この名前の変数を宣言できない場合、なぜ for ブロックの外部で 'i' の値を使用できないのでしょうか?
for ループで使用される反復変数はそのスコープ内でのみ有効であると考えていました。
ベストアンサー1
for ループ内と for ループ外の両方で同じ名前の変数を定義できない理由は、外側のスコープ内の変数が内側のスコープ内で有効であるためです。つまり、これが許可されている場合、for ループ内に 2 つの「i」変数が存在することになります。
見る:MSDN スコープ
具体的には:
ローカル変数宣言(セクション 8.5.1)で宣言されたローカル変数のスコープは、宣言が行われるブロックです。
そして
for 文の for 初期化子 (セクション 8.8.3) で宣言されたローカル変数のスコープは、for 初期化子、for 条件、for イテレータ、および for 文に含まれる文です。
さらに:ローカル変数の宣言(C#仕様のセクション8.5.1)
具体的には:
ローカル変数宣言で宣言されたローカル変数のスコープは、宣言が行われるブロックです。ローカル変数のローカル変数宣言子の前のテキスト位置でローカル変数を参照するのはエラーです。ローカル変数のスコープ内で、同じ名前を持つ別のローカル変数または定数を宣言すると、コンパイル時エラーになります。
(強調は私によるものです。)
つまり、forループの内側のスコープはi
forループです。一方、i
forループの外側のスコープはメインメソッド全体です。プラスfor ループ。つまり、i
ループ内に が 2 回出現することになりますが、これは上記によれば無効です。
これが許可されない理由は、ループ内での使用にのみスコープが設定されているint A = i;
ためです。したがって、ループ外からはアクセスできなくなります。int i
for
for
ご覧のとおり、これらの問題は両方ともスコープの結果です。最初の問題 ( ) は、ループ スコープ内に 2 つの変数int i = 4;
が存在することになります。一方、はスコープ外の変数にアクセスすることになります。i
for
int A = i;
代わりに、メソッド全体にスコープを宣言しi
、メソッドと for ループ スコープの両方でそれを使用することも考えられます。これにより、どちらのルールにも違反することがなくなります。
public static void Main()
{
int i;
for (i = 0; i < 5; i++)
{
}
// 'i' is only declared in the method scope now,
// no longer in the child scope -> valid.
i = 4;
// 'i' is declared in the method's scope -> valid.
int A = i;
}
編集:
もちろん、C# コンパイラを変更して、このコードが適切にコンパイルされるようにすることもできます。結局のところ、これは有効です。
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
for (int i = 5; i > 0; i--)
{
Console.WriteLine(i);
}
しかし、次のようなコードを記述できれば、コードの可読性と保守性に本当に役立つでしょうか。
public static void Main()
{
int i = 4;
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
for (int i = 5; i > 0; i--)
{
Console.WriteLine(i);
}
Console.WriteLine(i);
}
ここでの間違いの可能性について考えてみましょう。最後に出力されるのは 0 でしょうか、それとも 4 でしょうか。これは非常に小さな例であり、追跡するのは非常に簡単ですが、外側を別の名前でi
宣言した場合よりも保守性と可読性が大幅に低下します。i
注意:
C#のスコープルールは、C++のスコープルールC++ では、変数は宣言された場所からブロックの終わりまでの範囲内でのみ有効です。これにより、コードは C++ で有効な構造になります。