语句块中的变量范围

fea*_*net 12 c# compiler-construction clr scope

for (int i = 0; i < 10; i++)
{
    Foo();
}
int i = 10; // error, 'i' already exists

----------------------------------------    

for (int i = 0; i < 10; i++)
{
    Foo();
}
i = 10; // error, 'i' doesn't exist
Run Code Online (Sandbox Code Playgroud)

根据我对范围的理解,第一个例子应该没​​问题.它们都不允许的事实似乎更奇怪.肯定'我'要么在范围内,要么不在范围内.

有什么不明显的范围我不明白这意味着编译器真的无法解决这个问题?或者只是一个保姆状态编译案例?

Eri*_*ert 17

根据我对范围的理解,第一个例子应该没​​问题.

您对范围的理解很好.这不是范围错误.它是简单名称错误的不一致用法.

int i = 10; //错误,'我'已经存在

这不是报告的错误.报告的错误是"名为i的局部变量不能在此范围内声明,因为它会给i赋予不同的含义,它已在子范围中用于表示其他内容 "

错误消息告诉您错误是什么; 再次阅读错误消息.没有人说声明之间存在冲突; 它说错误是因为它改变了简单名称的含义.错误不是重新声明; 在两个具有相同名称的不同范围内拥有两个东西是完全合法的,即使这些范围嵌套.什么是合法的是有一个简单的名字的意思是两个不同的东西在嵌套的局部变量声明空间.

你会得到错误"一个名为i的局部变量已在此范围内定义",而不是你做了类似的事情

int i = 10;
int i = 10;
Run Code Online (Sandbox Code Playgroud)

肯定'我'要么在范围内,要么不在范围内.

当然 - 但是那又如何呢?给定的i是否在范围内是无关紧要的.例如:

class C 
{
    int i;
    void M()
    {
        string i;
Run Code Online (Sandbox Code Playgroud)

完全合法.外部i在整个M的范围内.声明一个影响外部范围的局部i没有任何问题.如果你说的话,会出现什么问题

class C 
{
    int i;
    void M()
    {
        int x = i;
        foreach(char i in ...
Run Code Online (Sandbox Code Playgroud)

因为现在你在两个嵌套的局部变量声明空间中使用了i来表示两个不同的东西 - 循环变量和字段.这令人困惑且容易出错,因此我们将其视为非法.

有什么不明显的范围我不明白这意味着编译器真的无法解决这个问题?

我不明白这个问题.显然,编译器能够完全分析程序; 如果编译器无法解析i的每次使用的含义,那么它如何报告错误消息?编译器完全能够确定您在同一局部变量声明空间中使用'i'表示两个不同的东西,并相应地报告错误.


kem*_*002 11

这是因为声明空间i在方法级别定义.该变量i在循环结束时超出范围,但您仍然无法重新声明i,因为i已在该方法中定义.

范围与宣言空间:

http://csharpfeeds.com/post/11730/Whats_The_Difference_Part_Two_Scope_vs_Declaration_Space_vs_Lifetime.aspx

你想看看Eric Lippert的回答(默认情况下,对于这些问题,他们总是正确的).

http://blogs.msdn.com/ericlippert/archive/2009/08/03/what-s-the-difference-part-two-scope-vs-declaration-space-vs-lifetime.aspx

以下是埃里克对上述帖子的评论,我想谈谈他们为什么做了他们所做的事情:

以这种方式看待它.在源代码中移动变量UP的声明应该始终是合法的,只要你将它保存在同一个块中,对吧?如果我们按照您的建议进行,那么这有时是合法的,有时是非法的!但我们真正想要避免的是C++中发生的事情 - 在C++中,有时移动变量声明实际上会改变其他简单名称的绑定!

  • 谢谢你的呐喊。夫妻的事。首先,这是一篇更好的文章:http://blogs.msdn.com/ericlippert/archive/2009/11/02/simple-names-are-not-so-simple.aspx,其次,最好是链接到原始文章而不是副本;这样,您就可以获取我的更新并阅读他人的评论:http://blogs.msdn.com/ericlippert/archive/2009/08/03/what-s-the-difference-part-two-scope-vs -declaration-space-vs-lifetime.aspx (2认同)

Zac*_*son 5

C#规范的局部变量声明:

在local-variable-declaration中声明的局部变量的范围是声明发生的块.

当然,现在,在声明i 之前你不能使用它,但i声明的范围是包含它的整个块:

{
    // scope starts here
    for (int i = 0; i < 10; i++)
    {
        Foo();
    }
    int i = 10;
}
Run Code Online (Sandbox Code Playgroud)

for i变量是在子作用域,因此变量名的冲突.

如果我们重新排列声明的位置,碰撞就会变得更清晰:

{
    int i = 10;

    // collision with i
    for (int i = 0; i < 10; i++)
    {
        Foo();
    }
}
Run Code Online (Sandbox Code Playgroud)