2010-02-05 65 views
7
interface IBar { void Hidden(); } 

class Foo : IBar { public void Visible() { /*...*/ } void IBar.Hidden() { /*...*/ } } 

class Program 
{ 
    static T CallHidden1<T>(T foo) where T : Foo 
    { 
     foo.Visible(); 
     ((IBar)foo).Hidden(); //Cast required 

     return foo; 
    } 

    static T CallHidden2<T>(T foo) where T : Foo, IBar 
    { 
     foo.Visible(); 
     foo.Hidden(); //OK 

     return foo; 
    } 
} 

有什麼不同(CallHidden1與CallHidden2)的實際編譯的代碼? T:Foo和T:Foo,IBar(如果Foo實現IBar)在訪問顯式實現的接口成員之間還有其他區別嗎?明確實現的接口和通用的限制

回答

1

是的,很小一點,因爲第二個指定必須實現接口,如果以後更改Foo以便它不實現IBar,這可能變得重要。

這將使得它不適合在CallHidden2<>在使用時在編譯時剩餘有效期爲​​(這樣會在運行時失敗,如果IBar不再被Foo實現)。

因此,如果他們在單獨的程序集中,不同的元數據會有所作爲。然而,執行的IL如果不相同,將會非常相似。

6

的IL產生稍有不同:

L_000d: ldarg.0 
    L_000e: box !!T 
    L_0013: callvirt instance void WindowsFormsApplication1.IBar::Hidden() 

L_000d: ldarga.s foo 
    L_000f: constrained !!T 
    L_0015: callvirt instance void WindowsFormsApplication1.IBar::Hidden() 

如果T是一個值類型,這將導致foo被裝箱在CallHidden1但不是在CallHidden2。但是,因爲Foo是一類,所以從Foo導出的任何類型T都不是值類型,因此行爲將是相同的。