2012-02-25 15 views
11

我讀過,引用類型保存對可能存儲在託管堆上的實際對象的引用。當一個方法被「分配」給委託引用變量時,引用指向哪個內存?這個內存塊與實際的功能代碼有什麼關係?代表指出什麼?

+0

不完全是你正在尋找的答案,但這篇文章可能會提供一些代表洞察http://stackoverflow.com/questions/527489/how-delegates-work-in-the-background – 2012-02-25 04:01:53

回答

14

讓我們拆開一個簡單的例子:

using System; 
class Program 
{ 
    delegate bool MyFilter(int x); 

    bool IsOdd(int x) 
    { 
     return x % 2 == 1; 
    } 

    static void Main() 
    { 
     MyFilter f = new Program().IsOdd; 
     Console.WriteLine(f(5)); 
    } 
} 

什麼是編譯器嗎?讓我們先從這一行:

delegate bool MyFilter(int x); 

編譯器生成一個,看起來有點像這樣:

class MyFilter : MulticastDelegate 
{ 
    public MyFilter(Object thisRef, IntPtr method); 
    public bool Invoke(int x); 
    // BeginInvoke(), EndInvoke() - Let's ignore those 
}  

類型MyFilter有一個接受兩個參數的構造函數:一個IntPtr到方法體調用,以及應該調用此方法的對象。 MyFilter類型的Invoke()方法調用實際的委託。

現在,讓我們來看看Main()方法中會發生什麼。編譯器會有點改寫這樣的:

static void Main() 
    { 
     MyFilter f = new MyFilter(new Program(), addressof(Program.IsOdd)); 
     Console.WriteLine(f.Invoke(5)); 
    } 

當然,addressof不是一個實際的C#運算符,但你能想象它會返回身體的地址方法傳遞項。另外,我沒有討論與代表有關的其他各種主題,如鏈接(這是MulticastDelegate基類提供的功能),但希望我解決了您的問題。

總而言之,委託引用指向實現與委託簽名匹配的Invoke方法的對象。該對象跟蹤指向需要調用的方法的指針,以及調用該方法的目標對象(除非方法是靜態的)。

0

實際上有兩種代表類型,DelegateMulticastDelegate。這些是從delegate的實際實例繼承的抽象類。我會推薦閱讀這些課程,因爲他們有比我在這裏解釋的更多(準確)詳細信息,但對於短版本:

雖然我不是100%確定實施如何正確工作,但最簡單的方法想象一個Delegate對象持有objectMethodInfo,這是特定方法的反射類型。 Delegate類型是抽象的原因是因爲Invoke方法取決於方法的參數。

同樣,MulticastDelegate保持多個Delegate對象,這些對象的每個點至個體object/MethodInfo組合。這允許event系統,其中一個event被觸發導致多個方法被調用。

讓我們回到實現細節,當你定義了一個代理,其與Invoke方法創建從MulticastDelegate繼承的類,也object可以null靜態方法。

除此之外,您還可以瞭解如何在調用之間傳遞對象MulticastDelegate,但我在這篇文章中可能已經犯了一些錯誤,所以我將在此處予以說明。

0

沒有給出過於複雜的答案,它指向(參考)存儲方法的實際內存塊。

0

委託實際上包含兩個地址 - 方法的地址以及對象的地址。這非常有趣,並且與代表有關的幾項專利授予Heljsberg http://www.google.com/patents/US6185728

這是非常有效的。在一個interview中,Heljsberg指出它可以比VTBL調度更有效率(因爲它是一個函數的直接指針)。在最簡單的情況下,它實際上是一個間接調用。例如

jmp *%eax 

總的來說,它需要4 instructions to execute a delegate