为什么Lambda变量范围存在于LINQ查询之外?

时间:2012-05-23 07:14:09

标签: c# .net linq scope

我读了这个问题(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查询中。

5 个答案:

答案 0 :(得分: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();
}

答案 1 :(得分:4)

让我们仔细看看,

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

如果x的范围以表达式

结尾
var x = somefunction()

现在这很有趣,这是针对包含lamda表达式的整个方法的范围,因此编译器无法区分,因为后者的范围与前者重叠。还有非常有用的信息给'x'赋予不同的含义,已经在'子'范围内使用 (在您的情况下选择)

Similar scope question

也许你可以在另一个周围包括大括号,以便定义范围

{
var x = somefunction()
}

答案 2 :(得分: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#不允许您编译具有在同一级别上存在的变量名称的程序

一切都是以非模糊方式向编译器表达 intent 。 C#在这方面做得很好

答案 3 :(得分:1)

(编译器)不清楚第二个'x'(=>之后)的'x'是什么意思。

如果你写了这个怎么办:

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

然后lambda中的x会与'somefunction'结果发生冲突。

答案 4 :(得分:1)

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

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

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

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

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

这是设计并适用于从int s到lambda引用的任何变量。