2012-07-14 45 views
3

可能重複之謎:
Detailed Explanation of Variable Capture in Closures揭開拉姆達如何工作

public class Polynom { 
    public delegate double Func(double x); 
    private Func f; 
    public Polynom(params double[] coef) { 
     f = (double x) => { 
     double sum = 0; 
     for (int i = 0 ; i < coef.Length ; i++) 
      sum += coef[i] * Math.Pow(x,coef.Length-1-i); 
     return sum; 
     }; 
    } 
    public double evaluate(double x) { 
     return f(x); 
    } 
    public static void Main() { 
     Polynom a=new Polynom(1,1,1); 
     Polynom b=new Polynom(2 , 2 , 0); 
     Console.WriteLine(a.evaluate(2)); 
     Console.WriteLine(b.evaluate(2)); 
     Console.ReadKey(); 
    } 
} 

請注意,在F中的代碼如何使用COEF,而COEF是構造的paramater。 如果你仔細想想,除非得到coef的ref拷貝,否則它不應該工作,因爲一旦構造函數完成了它的工作,它的參數就會消失。但不知何故,調用f設法使用coef,好像它仍然存在。怎麼樣?

我會愛一個良好的深explantion如果有人能解釋這個...

,我想知道的是另一件事,代碼爲每個多項式實例相同,但每一個實例獲得另一個副本相同的代碼?如果是這樣,有沒有辦法讓我的課程只運行該代碼的一個副本? (如獲得某種靜態)

+0

這已經被問過很多次。 – 2012-07-14 14:42:05

+0

它是?那麼答案是什麼呢? – 2012-07-14 14:44:37

+0

下面是一個問題,在下一步中詢問它:http://stackoverflow.com/questions/6013094/why-does-code-generate-msil-class-called-c-displayclass1你的下一步應該是加載你的在JustDecompile或ildasm中進行組裝,並查看編譯器如何創建代表lambda表達式的代碼。 – 2012-07-14 14:48:19

回答

2

Lambda和其他代表實現爲closures,這是由編譯器創建的特殊對象,它將您的lambda的方法與lambda需要完成其執行的所有數據結合起來。在lambda內部使用的所有局部變量和參數的值都隱式捕獲爲閉包的數據成員,所以它們保持可用,直到不再引用lambda本身爲止。

您可以將閉包看作專門爲您的lambda創建的特殊匿名類。在你的情況下,關閉可能是這樣的:

private Polynom_Closure { 
    private readonly double[] coef; 
    public Polynom_Closure(double[] coef) { 
     this.coef = coef; 
    } 
    public double evaluate(double x) { 
     double sum = 0; 
     for (int i = 0 ; i < coef.Length ; i++) 
      sum += coef[i] * Math.Pow(x,coef.Length-1-i); 
     return sum; 
    } 
} 

編譯器,使該類看不見你,然後插入其使用到您的代碼:

public Polynom(params double[] coef) { 
    f = new Polynom_Closure(coef).evaluate; 
} 
+0

不再需要,因爲它不再被引用? – 2012-07-14 14:48:58

+0

@OfekRon是的,我更正了答案,以便更具體地瞭解它。我還添加了一個小例子。 – dasblinkenlight 2012-07-14 14:51:16

+0

關於第二個問題的任何想法? – 2012-07-14 14:53:54

2

功能是所謂的封閉,在this wikipedia article

這是很好解釋的閉包允許函數訪問外其直接詞法範圍的變量。 upvalue是一個自由變量,它已經被一個閉包綁定(關閉)。據說封閉「關閉」了其價值。引用環境在創建閉包時將非本地名稱綁定到作用域中的相應變量,並將其生存期延長至至少與封閉本身的壽命一樣長。當稍後輸入閉包時,可能來自不同的作用域,該功能將通過其非本地變量引用由閉包捕獲的變量來執行。

關於第二個問題:使靜態閉包與功能原理的目的有些矛盾。