2011-05-27 33 views
6

我有以下代码段的局部变量不能在此范围中声明[LINQ的/ Lambda表达式]

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”的局部变量不能在此范围内声明

+2

这段代码的上下文是什么? – SirPentor 2011-05-27 17:31:10

+0

@Tobias:我修改了我的代码 – 2011-05-27 17:33:24

回答

16

你的问题是在这里:

// 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); 
+0

@Dan:你的意思是lambda变量是全局的吗? – 2011-05-27 17:35:10

+1

@geek:不,它不是全球性的。我会更新我的答案,以更好地解释... – 2011-05-27 17:36:48

+0

@丹涛:好的先生 – 2011-05-27 17:37:53

0

你的问题是,你认为闭包是C#中的第一类函数,情况并非如此,我希望它是这种情况。

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

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

JavaScript允许这种含糊不清,它允许无限制地编写闭包,这使闭包JavaScript的一流功能成为可能。

相关问题