【问题标题】:Why I cannot declare the variable with same name that already declared but new variable is out of the scope of other variable为什么我不能声明已声明的同名变量但新变量超出了其他变量的范围
【发布时间】:2012-03-12 07:23:13
【问题描述】:
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;
        //}
    }
}

我不明白:为什么我不能在foreach 循环之外声明变量,因为编译器给出了一个变量已经声明的错误。 foreach(以及 target 变量)的范围已经超出了我声明这个新变量的位置。

【问题讨论】:

  • 这是由选择 - 编译器希望帮助您避免一些非常常见的错误。例如,F# 确实允许这样的事情(即使在同一范围内),但它有助于不可变/功能范式
  • 虽然这是个好问题,但这里有很多重复项。其中之一:stackoverflow.com/questions/2059210/….

标签: c# foreach scope


【解决方案1】:

局部变量的范围一直延伸到声明它的块的开头。所以你的 second 声明的范围实际上是整个外部foreach 循环。来自 C# 4 规范,第 3.7 节:

在局部变量声明(第 8.5.1 节)中声明的局部变量的范围是声明所在的块。

在第 8.5.1 节中:

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

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

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

【讨论】:

  • 先生,为什么我们不能使用它(第一个声明的变量),或者如果第二个变量在一个 if 块内,那么编译器不会给出任何错误?
  • @Harikrishna:很难解析您的评论,但如果您有一个额外的 if 块,那么这会进一步限制第二个声明的范围 - 请阅读我引用的规范部分。
  • 我想问的是,为什么我们不能在第一个 if 块中使用第一个声明的变量,比如 target = "aa"?
  • @Harikrishna:对不起,我还是没听懂你的评论……但我认为我的回答解释了你看到的编译时错误。
【解决方案2】:

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

{
string target .....
}

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

【讨论】:

  • 不,第二个声明是 foreach 循环的范围,而不是整个方法。局部变量的范围是声明它的块 - 请参阅我的答案。
  • @JonSkeet 感谢您指出,在确定结尾大括号时出错
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多