在《C#高級編程》一書中提到通過Lambda表達式可以訪問Lambda表達式塊外部的變量 ,這是一個很好的功能(類似Js中的 閉包)。但是如果沒有正確的使用,會非常危險。
比如下面的事例中
int someVal = 5;
Fun<int, int> f = x => x + someVal;
Console.WriteLine(f(3));
我們這個表達式的本意是返回一個數x+5的結果。所以f(3)的結果應該是 3 + someVal = 8。
但是如果以后在不經意中修改了someVal的值,則會出現我們意想不到的結果。
比如:
someVal = 7;
Console.WriteLine(f(3));
此時的打印的結果是10。
特別是當通過多個線程調用Lambda時,我們可能不知道此時someVal的值到底是多少,從而導致不可預知的結果,所以要慎重使用。
那么,在Lambda表達式中使用外部變量的原理是什么呢。
原來,在運行Lambda表達式時,編譯器會創建一個匿名類,他可以通過構造函數來傳遞外部變量。該構造函數的參數取決於外部傳遞進來的變量個數。對於上面的表達式,匿名類如下所示:
public class AnonymousClass {
private int someVal;
public AnonymousClass(int someVal) { this.someVal = someVal; }
public int Anonymous(int x) { return x + someVal; }
}
這樣就可以理解為什么Lambda表達式可以使用外部變量了。