5

我读了这个问题(What is the scope of a lambda variable in C#?

但它是关于 LINQ Query 中的 Lambda 变量范围。

现在回答我的问题

假设我有一个非常简单的 LINQ 查询。

var Foo = FoobBar.Select(x => x);
var x = somefunction();

编译器说:A local variable 'x' cannot be declared in this scope because it would give a different meaning to 'x', which is already used in a 'child' scope to denote something else

为什么呢?LINQ 查询结束时,Lambda 变量不应该不复存在吗?

编辑:阅读答案后,我得出结论,它的x范围在 LINQ Query 内部扩展(从函数返回)。

4

5 回答 5

9

这与 LINQ 无关,而与子作用域有关。

例如:

foreach (var bar in FooBar.Bars)
        {
            var x = FooBar.GetFoo();
        }
var x = new Foo();

从编译器产生完全相同的错误消息。

要解决这个问题,您只需将变量放在不同的(非嵌套)范围内。例如:

foreach (var bar in FooBar.Bars)
        {
            var x = FooBar.GetBar();
        }
{
    var x = new Foo();
}
于 2012-05-23T07:23:23.493 回答
4

让我们仔细看看,

var Foo = FoobBar.Select(x => x);

true x 的范围以表达式结尾

var x = somefunction()

现在这很有趣,这也适用于包含 lamda 表达式的整个方法,因此编译器无法区分,因为后者的范围与前者重叠。并且非常有用的消息也给“x”赋予了不同的含义,它已经在“子”范围内使用 (根据您的情况选择)

类似范围问题

也许您可以在另一个周围包含大括号,以便定义它的范围

{
var x = somefunction()
}
于 2012-05-23T07:16:34.167 回答
2

想想如果 C# 允许这两个变量存在于同一范围级别,这是不可能的:

static void test() {

    Action<int> x = (z) => {
        Console.WriteLine(z);               
    };


    int[] i = { 5,2,0,1,3,1,4 };

    var kyrie = i.Select (x => x);

}

你会如何对 C# 说你想将名为 x 的 Action 委托分配给 kyrie 变量;反之亦然,你会如何对 C# 说你想使用整数投影本身?C# 将如何解决这个问题?

而且 C# 作用域解析是非常一致的,无论您在其他变量之前还是在其他变量之后声明它,它们都是相同的。例如http://www.anicehumble.com/2012/05/java-said-c-said-scope-consistency.html

为了消除这些情况的歧义,C# 不允许您编译具有相同级别的变量名称的程序

这一切都是为了以明确的方式向编译器表达你的意图。而 C# 在这方面做得很好

于 2012-05-23T07:45:42.150 回答
1

(编译器)不清楚第二个“x”(在 之后=>)是指哪个“x”。

如果你这样写:

var Foo = FoobBar.Select(y => x);
var x = somefunction();

那么xlambda中的那个会与'somefunction'结果发生冲突。

于 2012-05-23T07:18:26.790 回答
1

您不能在同一范围内声明两个具有相同名称的变量。

“相同范围”意味着它们都在当前范围内

void method()
{
    int a;
    int a; //wrong!
}

或者一个在当前范围内,另一个在子范围内。

void method()
{
    int a;
    for(;;)
    {
        int a; //wrong again!
    }
}

这是设计使然,适用于任何变量,从ints 到 lambda 引用。

于 2012-05-23T07:28:28.430 回答