不能在此作用域[Linq/Lambda表达式]中声明局部变量

本文关键字:表达式 声明 局部变量 Lambda 作用域 Linq 不能 | 更新日期: 2023-09-27 17:57:46

我在c#中有以下代码片段

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"的局部变量

不能在此作用域[Linq/Lambda表达式]中声明局部变量

您的问题在这里:

// 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();

要理解为什么这是一个问题,请考虑以下代码:

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的范围内访问。

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

这就是为什么存在歧义的原因,也是为什么不允许出现歧义的原因。


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

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

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

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

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

JavaScript允许这种模糊性,允许无限制地编写闭包,这使得闭包成为JavaScript的第一类函数。