C#变量范围';x';无法在此范围中声明,因为它将赋予';x';

C#变量范围';x';无法在此范围中声明,因为它将赋予';x';,c#,scope,C#,Scope,这将导致: 错误1名为“var”的局部变量 无法在此作用域中声明 因为它会给人一种不同的感觉 对“var”的含义,已经是 在“子”范围中用于表示 还有别的 真的没有什么惊天动地的,但这不是完全错了吗?我和一位开发人员同事想知道第一个声明是否应该在不同的范围内,因此第二个声明不能干扰第一个声明 为什么C#无法区分这两个范围?第一个IF范围是否应该与方法的其余部分完全分开 我无法从if外部调用var,因此错误消息是错误的,因为第一个var与第二个范围无关。这里的问题主要是良好实践和防止意外错误。诚然

这将导致:

错误1名为“var”的局部变量 无法在此作用域中声明 因为它会给人一种不同的感觉 对“var”的含义,已经是 在“子”范围中用于表示 还有别的

真的没有什么惊天动地的,但这不是完全错了吗?我和一位开发人员同事想知道第一个声明是否应该在不同的范围内,因此第二个声明不能干扰第一个声明

为什么C#无法区分这两个范围?第一个IF范围是否应该与方法的其余部分完全分开


我无法从if外部调用var,因此错误消息是错误的,因为第一个var与第二个范围无关。

这里的问题主要是良好实践和防止意外错误。诚然,C#编译器在理论上可以设计为在这里范围之间没有冲突。然而,在我看来,这将是一个事半功倍的过程

考虑一下,如果父范围中
var
的声明在if语句之前,则会出现无法解决的命名冲突。编译器只是不区分以下两种情况。分析完全基于范围,而不是您所期望的声明/使用顺序

理论上可以接受(但就C#而言仍然无效):

和不可接受的(因为它将隐藏父变量):

在变量和作用域方面,两者被完全相同地对待

现在,在这篇文章中,有什么实际的原因不能给其中一个变量起一个不同的名字吗?我假设(希望)您的实际变量不被称为
var
,所以我并不认为这是一个问题。如果仍然打算重用相同的变量名,只需将它们放在同级作用域中:

string var = "New VAR!";

if(true)
{
    string var = "VAR";
}

但是,这对编译器来说是有效的,在读取代码时会导致一些混乱,所以我建议在几乎任何情况下都反对它。

< P>这在C++中是有效的,但对于许多bug和不眠之夜来说是一个来源。我认为C#伙计们决定最好抛出一个警告/错误,因为在绝大多数情况下,它是一个bug,而不是程序员真正想要的东西

关于这个错误来自规范的哪些部分,有一个有趣的讨论

编辑(一些示例)-----

<>在C++中,下面的方法是有效的(并且,如果外部声明在内部范围之前或之后并不重要,它将更有趣,而且如果以前是错误的话)。
void foo(int a)
{
整数计数=0;
对于(int i=0;i
现在假设函数长几行,可能很容易发现错误。编译器从不抱怨(以前不是这样,不确定C++的新版本),函数总是返回0

该行为显然是一个bug,因此如果c++-lint程序或编译器指出这一点就好了。如果不是bug,只需重命名内部变量即可轻松解决

雪上加霜的是,我记得GCC和VS6对for循环中的反变量的归属有不同的看法。一个说它属于外部范围,另一个说它不属于外部范围。处理跨平台代码有点烦人。让我再举一个例子,让我的队伍不断壮大

void foo(int a)
{
    int count = 0;
    for(int i = 0; i < a; ++i)
    {
        int count *= i;
    }
    return count;
}
for(int i=0;i<1000;++i)
{
if(数组[i]>100)
打破
}
printf(“数组中第一个非常大的值存在于%d\n”,i);
这段代码在VS6 IIRC中工作,而不是在GCC中。无论如何,C#已经清理了一些东西,这很好

这难道不是大错特错吗

不,这完全没有错。这是C#规范第7.5.2.1节“简单名称,块中不变含义”的正确实现

该规范规定:


对于给定事件的每次出现 标识符,作为 表达式或声明器,在 局部变量声明空间 在那次事件中,每 同一事件的其他发生 标识符,作为 表达式或声明符必须引用相同的 实体。这条规则确保 名字的意思总是一样的 在给定的块内,开关块, for-、foreach-或using语句,或 匿名函数


为什么C#无法区分这两个范围

这个问题是荒谬的;显然,编译器能够区分这两个作用域。如果编译器无法区分这两个作用域,那么如何产生错误?错误消息说有两个不同的作用域,因此作用域已被区分

第一个IF范围是否应该与方法的其余部分完全分开

不,不应该。由块语句在条件语句的结果中定义的范围(和局部变量声明空间)在词汇上是定义方法体的外部块的一部分。因此,关于外部块内容的规则适用于内部块的内容

我不能从if外部调用var, 所以错误信息是错误的,因为 第一个风险值与第二个风险值无关 第二个范围

这是完全错误的。仅仅因为局部变量不再在作用域中,外部块不包含错误的结论是似是而非的。错误消息是正确的

这里的错误与任何变量的范围是否与任何其他变量的范围重叠无关;这里唯一相关的是,在wh中有一个块——外部块
string var = "New VAR!";

if(true)
{
    string var = "VAR";
}
if(true)
{
    string var = "VAR";
}

{
    string var = "New VAR!";
}
void foo(int a)
{
    int count = 0;
    for(int i = 0; i < a; ++i)
    {
        int count *= i;
    }
    return count;
}
for(int i = 0; i < 1000; ++i)
{
    if(array[i] > 100)
        break;
}

printf("The first very large value in the array exists at %d\n", i);
class C 
{
    int x;
    void M()
    { 
        int x = 123;
    }
}
class C 
{
    int x;
    void M()
    { 
        Console.WriteLine(x);
        if (whatever)
        {
            int x = 123;
        }
    }
}
class C 
{
    int x;
    void M()
    { 
        if (whatever)
        {
            Console.WriteLine(x);
        }
        if (somethingelse)
        {
            int x = 123;
        }
    }
}