2009-11-05 76 views
9

我認爲委託實例可以與函數實例互換。委託實例和方法指針有什麼區別?

看看下面的代碼:

delegate int AddDelegate(int a, int b); 

AddDelegate DelegateInstance; 

public void DoStuff() 
{ 
    //I can call this without a delegate "instance": 
    MethodThatTakesAdd(Add); 

    //I can also call it WITH a delegate "instance" 
    DelegateInstance = Add; 
    MethodThatTakesAdd(DelegateInstance); 
} 

public int Add(int a, int b) 
{ 
    return a + b; 
} 

public void MethodThatTakesAdd(AddDelegate addFunction) 
{ 
    Console.WriteLine(addFunction(1, 2).ToString()); 
} 

調用它似乎相當於的兩種方式,如果你只使用C#中,你永遠不會看到其中的差別(至少我還沒有達到這點)。不過,我最近是託管代碼的非託管代碼,它們的處理方式不同。例如,在一種情況下,如果我直接將該函數用作回調函數(即使我的對象實例保留在附近),我將得到錯誤「回調是在垃圾回收委託上進行的」。使用「委託實例」可以解決問題。

有沒有人知道有什麼區別?

+1

il是什麼樣的?有沒有任何跡象表明「底層」,他們通常會被區別對待? – 2009-11-05 16:53:03

回答

13

術語糾正:代替方法指針,更合適的術語是方法組。

就功能而言,兩條語句是等價的。那就是他們生產的差不多是的同一個IL。區別在於委託值的存儲位置。

在第一種情況傳遞方法組添加到MethodThatTakesAdd直接。這會導致創建臨時委託值,然後傳遞給MethodThatTakesAdd。這個委託值在MethodThatTakesAdd返回的那一刻進行垃圾回收,因爲它不存儲該值。

在第二種情況下你分配委託給一個字段在外實例。這將通常增加委託的生命週期,從而減少在您的銷售電話期間垃圾收集的機會。

+0

這聽起來很合理,並且會解釋我所看到的! – 2009-11-05 16:57:43

+0

http://msdn.microsoft.com/en-us/magazine/cc164193.aspx解釋了它在「反向的P/Invoke和代表終身」部分 – 2009-11-05 17:32:32

+0

@JaredPar我不明白。這個'AddDelegate DelegateInstance;'是一個委託**實例** ??它只是一個'AddDelegate'類型的變量。代表**實例**將成爲myDel + = new MYDEL(myMethod);或myDel + = myMethod;(簡稱)的**右側**似乎是合乎邏輯的。 。我錯了嗎 ? – 2013-05-03 07:52:32

0

雖然代表提供在C#作爲在C或C++函數指針同義的功能,也有顯著差異。這些中的關鍵是一個代表是一個類,而不是一個指針。

總之,鑄造一個委託的指針是不會給你的功能或方法的引用,因此它不能用於通過從非託管代碼參考調用的方法。

4

委託是可調用的類,並具有類似行爲到函數指針。委託內部存儲要調用的函數的地址(即函數指針),但也提供其他功能,如多播和存儲調用列表;你可以使用一個委託實例來調用相同簽名的許多函數,如下所示。

public void DoStuff() 
{ 
    DelegateInstance += Add; 
    DelegateInstance += AnotherAdd; 
    DelegateInstance += YetAnotherAdd; 

    // Invoke Add(100, 200), AnotherAdd(100, 200), and YetAnotherAdd(100, 200) 
    DelegateInstance(100, 200); 
} 

關於你關於MethodThatTakesAdd(Add)MethodThatTakesAdd(DelegateInstance), 等價注:如果你看一下MSIL的C#編譯器生成行MethodThatTakesAdd(Add),你會發現,編譯器創建委託和包裝的Add()方法爲你。

相關問題