如何解决C#中的可变范围混淆
这里有两个相关的规则。
第一条相关规则是:
(此页面上的另一个答案将在规范中调出另一个位置,我们再次将其调出。)
仅此一项就足以使这种违法,但实际上,第二条规则使这种违法成为可能。
C#中的第二条相关规则是:
对于表达式或声明符中给定标识符的每个简单名称的每次出现,在局部变量声明空间内,立即将其所在的块或切换块括起来,在该示例中,每隔一次出现与简单名称相同的标识符直接封闭的块或switch- block中的表达式或声明符必须引用同一实体。该规则确保名称的含义在给定的块,切换块,for,foreach或using语句或匿名函数中始终相同。
(更新:此答案写于2009年;在C#的最新版本中,此规则已被删除,因为它被认为过于混乱;用户产生的混乱不值得一小部分被阻止的错误。有关详细信息,请参见此答案。 )
您还需要知道,将for循环视为好像整个事物周围都存在“不可见的花括号”一样。
现在我们知道了,让我们注释一下代码:
public void MyMethod()
{ // 1
int i=10; // i1
{ // 2 -- invisible brace
for(int x=10; x<10; x++) // x2
{ // 3
int i=10; // i3
var objX = new MyOtherClass(); // objX3
} // 3
} // 2
var objX = new OtherClasOfmine(); // objX1
} // 1
您有三个“简单名称”,即i,x和objX。您有五个变量,我将它们标记为i1,x2,i3,objX3和objX1。
包含i和objX用法的最外面的块是块1。因此,在块1内,i和objX必须始终引用同一事物。但是他们没有。有时我指的是i1,有时指的是i3。与objX相同。
但是,x在每个块中仅表示x2。
同样,两个“ i”变量和两个“ objX”变量都在同一局部变量声明空间中。
因此,该程序在几种方面都是错误。
在第二个程序中:
public void MyMethod()
{ // 1
{ // 2 -- invisible
for(int x=10; x<10; x++) // x2
{ // 3
int i=10; // i3
var objX = new MyOtherClass(); // objX3
} //3
} // 2
{ // 4 -- invisible
for(int x=10; x<10; x++) // x4
{ // 5
int i=10; // i5
var objX = new MyOtherClass(); // objX5
} //5
} // 4
} // 1
现在,您又有了三个简单的名称和六个变量。
首先包含简单名称x用法的最外面的块是块2和4。在整个块2中,x表示x2。在整个方框4中,x表示x4。因此,这是合法的。与i和objX相同- 它们分别在第3块和第5块中使用,并且各自含义不同。但是,在同一块中,没有一个简单的名称用来表示两个不同的事物。
现在,您可能会注意到, ,x用于表示x2和x4。但是没有提及x位于块1内,而没有提及另一个块内。因此,我们不会将块1中的不一致用法视为相关。
而且,没有任何声明空间以非法方式重叠。
因此,这是合法的。
解决方法
我有两个代码示例。第一个不编译,但是第二个编译。
代码示例1 (不编译)
public void MyMethod(){
int i=10;
for(int x=10; x<10; x++) {
int i=10; // Point1: compiler reports error
var objX = new MyOtherClass();
}
var objX = new OtherClassOfMine(); // Point2: compiler reports error
}
我了解为什么编译器会在上报告错误Point1
。但我不明白为什么它会在上报告错误Point2
。如果您说这是由于MSIL内部的组织造成的,那么为什么第二个代码示例会进行编译?
代码示例2 (编译)
public void MyMethod(){
for(int x=10; x<10; x++) {
int i=10;
var objX = new MyOtherClass();
}
for(int x=10; x<10; x++) {
int i=10;
var objX = new MyOtherClass();
}
}
如果变量范围的简单规则适用于代码示例2,那么为什么这些规则不适用于代码示例1?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。