2010-11-17 26 views
3

綁定在瓦格納的「Effective C#」,第23項,他解釋說,接口早/晚在.net

接口方法不是 虛擬...他們是一個 具體實現的聲明。

我發現這是一個難題,因爲它意味着接口方法代表了早期綁定,但它們具有後期綁定的行爲。它喚起了他們如何在封面下工作的好奇心。在C++中,這將變成對vtables的討論。在C#中,我不知道它變成了什麼。有人能說出來嗎?

p.s.這個問題有a cousin,但是這個問題關注於接口。
p.p.s.請不要擔心「你不需要知道它是如何工作的。」這又是一個好奇心。

回答

6

對,從語言的角度來看,它們並不是虛擬的。但他們實際上就CLR而言。此示例代碼:

class Example : IDisposable { 
    public void Dispose() {} 
} 

生成此IL爲Dispose()方法:

.method public hidebysig newslot virtual final // <=== here 
     instance void Dispose() cil managed 
{ 
    // Unimportant 
} // end of method Example::Dispose 

註上的方法中的屬性:虛擬最終。最後是確保你不能重寫派生類中的方法。使接口方法的實現像語言中的非虛擬方法一樣,但在運行時是虛擬方法。

然後這也回答你關於早/晚綁定的問題。現在很早,當班級被加載時,v表格插槽被填充。

+0

顯然你的文章是我的答案。只有一個細節。你說一個接口代表早期綁定,但它肯定會展示後期綁定:'foreach(IMyInterface foo in Yahoo)foo.Run();'。在這種情況下,確定哪個'Run'方法要在加載類後發生,是嗎?那不是遲到的約束? – 2010-11-17 21:34:55

+1

@Brent Arias - 這取決於你對「遲綁定」的定義。請參閱http://stackoverflow.com/questions/3842102/c-polymorphism/3842173#3842173 – 2010-11-17 21:51:10

+1

不,這是早期的限制。可以在不需要搜索可能的候選方法列表的情況下進行調用。遲綁定具有明確的含義,在C#中它涉及* dynamic *關鍵字或System.Reflection。關於接口方法調用的關鍵點是它們總是*間接調用(callvirt),而不是直接調用。儘管該語言表示他們不是虛擬的。 (我會避免提到C#甚至在非虛方法上使用callvirt來獲得廉價的空檢查)。 – 2010-11-17 21:51:23