C# 为什么我不能用已经声明的相同名称声明变量,但新变量超出了其他变量的范围

C# 为什么我不能用已经声明的相同名称声明变量,但新变量超出了其他变量的范围,c#,foreach,scope,C#,Foreach,Scope,我无法理解:为什么我不能在foreach循环之外声明变量,因为编译器给出了一个错误,即变量已经声明了。foreach(因此target变量)的范围超出了我声明这个新变量的范围。局部变量的范围一直延伸到声明它的块的开头。因此,第二个声明的范围实际上是整个外部foreach循环。根据C#4规范第3.7节: 局部变量声明(§8.5.1)中声明的局部变量的范围是声明发生的块 第8.5.1节: 局部变量声明中声明的局部变量的作用域是发生声明的块。在局部变量的局部变量声明符之前的文本位置引用局部变量是错误的

我无法理解:为什么我不能在
foreach
循环之外声明变量,因为编译器给出了一个错误,即变量已经声明了。
foreach
(因此
target
变量)的范围超出了我声明这个新变量的范围。

局部变量的范围一直延伸到声明它的块的开头。因此,第二个声明的范围实际上是整个外部
foreach
循环。根据C#4规范第3.7节:

局部变量声明(§8.5.1)中声明的局部变量的范围是声明发生的块

第8.5.1节:

局部变量声明中声明的局部变量的作用域是发生声明的块。在局部变量的局部变量声明符之前的文本位置引用局部变量是错误的。在局部变量的范围内,使用相同的名称声明另一个局部变量或常量是编译时错误

因此,即使第二个变量没有在第一个变量出现的地方声明,它仍然在范围内-因此它们之间的两个声明违反了8.5.1


这种语言的设计是为了防止错误——如果只是在声明局部变量的块内移动局部变量声明的位置,并且在第一次使用之前更改了代码的有效性,那就太奇怪了。

这是因为第二次声明是针对第一次声明的方法范围的整个范围的
foreach
循环,包括方法中包含的第二个
foreach
循环。因此,您需要的是使用大括号限制其他字符串的范围

private void Abc()
{
    string first="";
    ArrayList result = new ArrayList();
    ArrayList secResult = new ArrayList();
    foreach (string second in result)
    {
        if (first != null)
        {
            foreach (string third in secResult)
            {
                string target;
            }
        }

        string target;//Here I cannot decalre it. And if I don't declare it and
        //want to use it then also I cannot use it. And if it is in if condition like
        //the code commented below, then there is no any complier error.
        //if (first != null)
        //{
        //    string target;
        //}
    }
}

这应该不是必需的,而且似乎是代码气味的标志,也许您需要将逻辑封装到单独的方法中。我会要求您再次检查代码,看看是否可以重建代码。

这是您的选择-编译器希望帮助您避免一些非常常见的错误。例如,F#确实允许这样的事情(即使在相同的范围内),但它有助于不可变/功能范式尽管这是一个好问题,但这里有很多重复。其中一个:。先生,为什么我们不能使用它(第一个声明的变量),或者如果第二个变量在一个if块内,那么编译器不会给出任何错误?@Harikrishna:很难解析您的评论,但是如果你有一个额外的
if
块,那么这就限制了第二个声明的范围——请进一步阅读我引用的规范部分。我想问的是,为什么我们不能在第一个if块中使用第一个声明变量target=“aa”?@Harikrishna:对不起,我仍然不理解你的评论。。。但是我认为我的回答解释了您看到的编译时错误。不,第二个声明是foreach循环的范围,而不是整个方法。局部变量的作用域是声明它的块-请参阅我的答案。@JonSkeet感谢您指出它,在确定结束大括号时是错误的
{
string target .....
}