2011-05-27 70 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的一流功能成爲可能。

相關問題