for循环中声明的variables是局部variables?

我一直在使用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'的值,如果它不允许我用这个名字来声明一个variables呢?

我认为for循环使用的迭代器variables只在其范围内有效。

不允许在for循环和for循环之外定义同名variables的原因是外部variables在内部范围内有效。 这意味着如果允许的话,for循环中将会有两个'i'variables。

请参阅: MSDN范围

特别:

局部variables声明中声明的局部variables的范围(见第8.5.1节)是声明出现的块。

在for语句的for-initializer中声明的局部variables的作用域(Section 8.8.3)是for语句的for-initializer,for-condition,for-iterator和contain语句。

还有: 局部variables声明 (C#规范的第8.5.1节)

特别:

局部variables声明中声明的局部variables的范围是声明出现的块。 在局部variables的局部variables声明符之前的文本位置引用局部variables是错误的。 在局部variables的范围内,声明另一个局部variables或具有相同名称的常量是编译时错误。

(强调我的)

这意味着你的for循环中的i的作用域是for循环。 而for循环之外的i的范围是整个主要方法 for循环。 这意味着你会有两次出现在循环内,这是无效的根据上述。

你不可以做int A = i; 是因为int i只是在for循环内使用的范围。 因此它不能在for循环之外访问。

正如你所看到的,这两个问题都是范围界定的结果。 第一个问题( int i = 4; )会在for循环范围内产生两个ivariables。 而int A = i; 会导致访问超出范围的variables。

你可以做什么,而不是宣布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); } 

想想这里的错误的可能性,最后i打印出0或4吗? 现在这是一个非常小的例子,它很容易跟踪和跟踪,但是与以外部名称声明相比,它的可维护性和可读性要低得多。

注意:

请注意,C#的范围规则不同于C ++的范围规则 。 在C ++中,variables只在声明的范围内,直到块的结尾。 这将使你的代码在C ++中成为一个有效的结构。

J.Kommer的回答是正确的:简而言之,在本地variables声明空间声明局部variables是非法的,该局部variables声明空间 另一个局部名称相同的局部variables声明空间 重叠

还有一个违反了C#的规则。 附加的规则是, 在两个不同的重叠局部variables声明空间内使用简单的名称来引用两个不同的实体是非法的。 所以不仅你的例子是非法的,这也是非法的:

 class C { int x; void M() { int y = x; if(whatever) { int x = 123; 

因为现在在“y”的局部variables声明空间内使用简单名称“x”来表示两个不同的东西 – “this.x”和本地“x”。

有关这些问题的更多分析,请参阅http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/

在循环之后的方法里面有一个声明和使用i的方法:

 static void Main() { for (int i = 0; i < 5; i++) { } { int i = 4; int A = i; } } 

你可以用Java来做到这一点(它可能源于C我不知道)。 为了variables名,当然有点麻烦。

如果你 for循环之前声明了i ,你认为在循环中声明它还是有效的吗?

不,因为这两者的范围会重叠。

至于不能做int A=i; ,那么这只是因为i只存在于for循环中,就像它应该这样做。

除了J.Kommer的回答(+1 btw)。 NET范围的标准是这样的:

如果在块结构(如If语句)中声明一个variables,则该variables的作用域仅在块的结尾处。 终身直到程序结束。

过程如果在一个过程中声明了一个variables,但是在任何If语句之外,范围将一直到End Sub或End Function。 variables的生命周期直到过程结束。

因此,for循环头文件中的int i将在for循环块中处于作用域, 但是它的生命期会持续到Main()代码完成。

想想这个最简单的方法是把I的外部声明移到循环的上面。 那应该变得明显了。

无论哪种方式都是一样的,所以不能这样做。

另外C#的规则在严格编程方面很多时候是不必要的,但是在那里保持你的代码清洁和可读。

例如,他们可以这样做,所以如果你在循环之后定义它,那么它是可以的,然而有人读你的代码而错过定义行可能会认为它与循环的variables有关。

Kommer的答案在技术上是正确的。 让我用一个生动的盲屏比喻来解释它。

在for-block和封闭的外部块之间有一个单向的盲屏,使得for-block中的代码可以看到外部代码,但是外部代码中的代码不能看到里面的代码。

由于外部代码看不到内部,因此不能使用内部声明。 但是由于for-block中的代码可以在内部和外部看到,所以在两个地方声明的variables不能被名称明确地使用。

所以要么你看不到,要么你C#!

以同样的方式来看待它,就好像你可以在一个using块中声明一个int

 using (int i = 0) { // i is in scope here } // here, i is out of scope 

但是,由于int不实现IDisposable ,所以不能这样做。 尽pipe如此,它可以帮助人们看到如何将一个intvariables放置在一个私有的范围内。

另一种方法是说,

 if (true) { int i = 0; // i is in scope here } // here, i is out of scope 

希望这有助于可视化发生的事情。

我真的很喜欢这个function,因为在for循环中声明int可以让代码更好,更紧密。