关于c#:无法在此范围内声明局部变量[Linq / Lambda表达式]

A local variable cannot be declared in this scope[Linq/Lambda expression]

我有以下C语言的代码片段#

1
2
3
4
5
6
7
8
9
10
static void Main()
{
    var numbers = new[] { 1, 2, 3, 4, 5, 6 };

    var ngt5 = numbers.Where(n => n > 5);

    var n = ngt5.First().ToString();

    Console.WriteLine(n, numbers);
}

当我编译上述代码时,我遇到了以下错误

不能在此范围中声明名为"n"的局部变量


你的问题在这里:

1
2
3
4
5
// Within your lambda you have an 'n'.
var ngt5 = numbers.Where(n => n > 5);

// And within the outer scope you also have an 'n'.
var n = ngt5.First().ToString();

要理解这是问题的原因,请考虑以下代码:

1
2
int n = 1000;
var evens = Enumerable.Range(1, 1000).Where(n => n % 2 == 0);

上面的表达式n % 2 == 0是不明确的:我们说的是哪个n?如果我们说的是外部的n,那么n % 2 == 0总是正确的,因为n只有1000(因此evens将包含从1到1000的所有数字)。另一方面,如果我们讨论的是内部n,那么n % 2 == 0只适用于n的偶数值(而evens将是2、4、6,…)。1000)。

要实现的重要的一点是,在lambda之外声明的变量可以从lambda范围内访问。

1
2
3
4
int n = 0;
Action incrementN = () => n++; // accessing an outer variable
incrementN();
Console.WriteLine(n); // outputs '1'

这就是歧义存在的原因,也是不允许歧义存在的原因。

解决方案只是为lambda选择一个不同的变量名;例如:

1
var ngt5 = numbers.Where(x => x > 5);


您的问题是,假设闭包是C中的第一类函数,但事实并非如此,我希望是这样。

不能将C闭包的作用域视为独立的函数作用域。

不能在当前范围之外返回复杂的LINQ表达式。

Javascript允许这种模糊性,允许不受任何限制地编写闭包,这使得闭包成为Javascript的第一类函数。