C# 儿童范围和 CS0136

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/296755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 22:06:35  来源:igfitidea点击:

Child Scope & CS0136

c#compiler-constructionscope

提问by JoshBerke

The following code fails to compile stating "A local variable named 'st' cannot be declared in this scope because it would give a different meaning to 'st', which is already used in a 'child' scope to denote something else":

以下代码无法编译,说明“无法在此范围内声明名为 'st' 的局部变量,因为它会给 'st' 赋予不同的含义,而 'st' 已在 '子' 范围中用于表示其他内容”:

        var l = new List<string>();
        l.Find(st => st.EndsWith("12"));
        string st = "why this fails?";

I understand why this won't work:

我明白为什么这行不通:

        string preParent = "";
        {
            string preParent = "Should fail cause we change the meaning";
        }

When we do the following we get "CS0103: The name 'postParent' does not exist in the current context":

当我们执行以下操作时,我们得到“CS0103:当前上下文中不存在名称‘postParent’”:

        {
            string postParent=string.Empty;
        }
        postParent = "Should this work?";

What I don't get is why is the compiler smart enough to see that postParent is not within scope, but won't let me define a new variable that has the same name as a variable used within a child scope (which is obviously out of scope at this point).

我不明白的是为什么编译器足够聪明,可以看到 postParent 不在范围内,但不会让我定义一个与子范围内使用的变量同名的新变量(这显然不在范围内)在这一点上的范围)。

Is the compiler simple enforcing scope by refusing to let me use the variable? If so this makes sense.

编译器是否通过拒绝让我使用变量来简单地强制执行范围?如果是这样,这是有道理的。

===========

============

Edited:

编辑:

I guess what I also find interesting is how you can have the same variable within two child scopes in a single method, so this is valid:

我想我还觉得有趣的是,如何在一个方法中的两个子作用域内拥有相同的变量,所以这是有效的:

        {
            string thisWorks= string.Empty;
        }
        {
            string thisWorks= "Should this work?";
        }

I'm just a little curious that you can have two variables with the same name as long as they are at the same level (if you look at scope as a tree). This makes sense because you can have local variables in two methods of the same class with the same name.

我只是有点好奇,你可以有两个同名的变量,只要它们处于同一级别(如果你把作用域看作一棵树)。这是有道理的,因为您可以在同一个类的两个同名方法中使用局部变量。

I'm just surprised that the compiler is able to differentiate and allow this, while it wouldn't allow the postParent variable. And is this a technical limitation or was this a design decision? That's what I'm really trying to get at;-)

我只是惊讶编译器能够区分并允许这样做,而它不允许 postParent 变量。这是技术限制还是设计决定?这就是我真正想要达到的;-)

采纳答案by Jon Skeet

Yes, the compiler is enforcing scope. Note that the scope of a variable is the lexical block it's part of - not just from the point of declaration onwards, but the whole scope.

是的,编译器正在强制执行范围。请注意,变量的作用域是它所属的词法块——不仅仅是从声明点开始,而是整个作用域。

The compiler is complaining because the assignment to postParentis outside its scope (which is only the nested braces). If you tried to declare a new variable at the point where you're currently assigning to postParentthe problem would be with the nested block, because the scope of postParentwould include that nested block, even though it was before the declaration.

编译器抱怨是因为赋值postParent超出了它的范围(这只是嵌套的大括号)。如果您试图在当前分配给postParent问题的点声明一个新变量,则问题将与嵌套块有关,因为范围postParent将包括该嵌套块,即使它在声明之前。

Scopes are described in section 3.7 of the C# 3.0 specification.

C# 3.0 规范的第 3.7 节中描述了作用域。

EDIT: To respond to your question edit.

编辑:回答您的问题编辑。

It's just two simple rules:

这只是两个简单的规则:

  • you can't declare a local variable when another local variable with the same name is in scope
  • the scope of a local variable is the block in which the declaration occurs
  • 当另一个同名的局部变量在范围内时,你不能声明一个局部变量
  • 局部变量的作用域是发生声明的块

I'm sure the language could have been designed such that the scope only began at the point of declaration, but I think it's simpler (in terms of language complexity) to consider scopes as just blocks - so all local variables declared in the same block have the same scope, for example. That makes life a lot simpler when considering captured variables, too - as what gets captured depends on the scope, and nested scopes make life interesting...

我确信该语言可以设计为范围仅从声明点开始,但我认为将范围视为块更简单(就语言复杂性而言) - 因此所有局部变量都在同一块中声明例如,具有相同的范围。在考虑捕获的变量时,这也使生活变得更加简单 - 因为捕获的内容取决于作用域,而嵌套作用域使生活变得有趣......

EDIT: The language spec has this to say about the original lambda expression example - it's section 7.14.1:

编辑:语言规范有关于原始 lambda 表达式示例的说明 - 它是第 7.14.1 节:

The optional anonymous-function-signature of an anonymous function defines the names and optionally the types of the formal parameters for the anonymous function. The scope of the parameters of the anonymous function is the anonymous-function-body. Together with the parameter list (if given), the anonymous-method-body constitutes a declaration space. For this reason, it is a compile-time error for the name of a parameter of the anonymous function to match the name of a local variable, local constant, or parameter whose scope includes the anonymous-method-expression or lambda-expression.

匿名函数的可选匿名函数签名定义了匿名函数的形式参数的名称和可选的类型。匿名函数的参数范围是匿名函数体。与参数列表(如果给定)一起,匿名方法体构成了一个声明空间。因此,如果匿名函数的参数名称与范围包括匿名方法表达式或 lambda 表达式的局部变量、局部常量或参数的名称相匹配,则会导致编译时错误。

Does that help?

这有帮助吗?

回答by Jared

You're declaring a variable in a limited scope and trying to use it outside of that scope. The compiler assumes you don't want access to it so you can declare a variable with the same name somewhere else in the file. Your trying to do the old C trick of assuming the variable will live immediately outside of the scope. For example this used to work in older versions of C/C++ but no longer does.

您在有限的范围内声明一个变量并尝试在该范围之外使用它。编译器假定您不想访问它,因此您可以在文件的其他位置声明一个具有相同名称的变量。您尝试执行旧的 C 技巧,假设变量将立即存在于范围之外。例如,这曾经在旧版本的 C/C++ 中工作,但不再适用。

for (int i=0; i<10; i++)
{
    cout <<”In the loop i is “<< i << endl;
}
cout << “outside of the loop i is “ << i << endl; //this only compiles with old C/C++ compilers.