C#中的变量范围混淆 [英] Variable scope confusion in C#

查看:20
本文介绍了C#中的变量范围混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个代码示例.第一个不编译,但第二个编译.

I have two code samples. The first does not compile, but the second does.

代码示例 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内部的组织,那第二个代码示例为什么要编译?

I understand why the compiler reports an error at Point1. But I don't understand why it reports an error at Point2. And if you say it is because of the organization inside MSIL, then why does the second code example compile?

代码示例 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?

If the simple rules of variable scope apply in Code Sample 2, then why don't those same rules apply to Code Sample 1?

推荐答案

这里有两个相关的规则.

There are two relevant rules here.

第一个相关规则是:

这是一个局部变量的错误声明空间和嵌套的本地要包含的变量声明空间具有相同名称的元素.

It is an error for a local variable declaration space and a nested local variable declaration space to contain elements with the same name.

(此页面上的另一个答案指出了规范中的另一个位置,我们在此处再次指出了这一点.)

(And another answer on this page calls out another location in the specification where we call this out again.)

仅此一项就足以使这成为非法,但实际上第二条规则使这成为非法.

That alone is enough to make this illegal, but in fact a second rule makes this illegal.

C# 中的第二条相关规则是:

The second relevant rule in C# is:

对于给定的每次出现标识符作为一个简单的名称表达式或声明符,在局部变量声明空间,立即封闭块,或该事件的开关块,每隔一次相同的标识符作为一个简单的名称表达式或声明符立即封闭块或switch-block 必须引用相同的实体.该规则确保名字的含义总是一样的在给定的块内,开关块,for-、foreach- 或 using-语句,或匿名函数.

For each occurrence of a given identifier as a simple-name in an expression or declarator, within the local variable declaration space, immediately enclosing block, or switch-block of that occurrence, every other occurrence of the same identifier as a simple-name in an expression or declarator within the immediately enclosing block or switch-block must refer to the same entity. This rule ensures that the meaning of a name is always the same within a given block, switch block, for-, foreach- or using-statement, or anonymous function.

(更新:这个答案是在 2009 年写的;在最近的 C# 版本中,这条规则被取消了,因为它被认为太混乱了;产生的用户混淆不值得被阻止的少量错误.有关详细信息,请参阅此答案.)

(UPDATE: This answer was written in 2009; in recent versions of C# this rule has been eliminated because it was considered to be too confusing; the user confusion produced was not worth the small number of bugs that were prevented. See this answer for details.)

您还需要知道 for 循环被视为整个事物周围有隐形括号".

You also need to know that a for-loop is treated as though there are "invisible braces" around the whole thing.

现在我们知道了,让我们注释您的代码:

Now that we know that, let's annotate your code:

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.

You have three "simple names", i, x and objX. You have five variables, which I've labeled i1, x2, i3, objX3, and objX1.

包含 i 和 objX 用法的最外层块是块 1.因此,在块 1 内,i 和 objX 必须始终指同一个事物.但他们没有.有时 i 指的是 i1,有时指的是 i3.与 objX 相同.

The outermost block that contains usages of i and objX is block 1. Therefore, within block 1, i and objX must always refer to the same thing. But they do not. Sometimes i refers to i1 and sometimes it refers to i3. Same with objX.

然而,x 在每个块中只表示 x2.

x, however, only ever means x2, in every block.

此外,两个i"变量都在同一个局部变量声明空间中,objX"变量也是如此.

Also, both "i" variables are in the same local variable declaration space, as are both "objX" variables.

因此,这个程序在几个方面都是错误的.

Therefore, this program is an error in several ways.

在你的第二个程序中:

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

现在您又有了三个简单的名称和六个变量.

Now you have three simple names again, and six variables.

首先包含使用简单名称 x 的最外面的块是块 2 和 4.在整个块 2 中,x 指的是 x2.在块 4 中,x 指的是 x4.因此,这是合法的.与 i 和 objX 相同——它们用于块 3 和块 5 中,并且在每个块中表示不同的含义.但在同一块中,没有任何地方使用相同的简单名称来表示两种不同的事物.

The outermost blocks that first contain a usage of simple name x are blocks 2 and 4. Throughout block 2, x refers to x2. Throughout block 4, x refers to x4. Therefore, this is legal. Same with i and objX -- they are used in blocks 3 and 5 and mean different things in each. But nowhere is the same simple name used to mean two different things throughout the same block.

现在,您可能会注意到考虑到所有块 1,x 用于表示 x2 和 x4.但是没有提到在块 1 内但不在另一个块内的 x.因此,我们不会将块 1 中的不一致用法视为相关.

Now, you might note that considering all of block 1, x is used to mean both x2 and x4. But there's no mention of x that is inside block 1 but NOT also inside another block. Therefore we don't count the inconsistent usage in block 1 as relevant.

此外,没有任何声明空间以非法方式重叠.

Also, none of the declaration spaces overlap in illegal ways.

因此,这是合法的.

这篇关于C#中的变量范围混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆