明确实现的接口和泛型约束

Tom*_*lan 7 c# generics explicit-interface

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有任何区别(CallHidden1与CallHidden2)是实际编译的代码?T:Foo和T:Foo,IBar(如果Foo实现IBar)在访问显式实现的接口成员时是否存在其他差异?

kvb*_*kvb 6

产生的IL略有不同:

    L_000d: ldarg.0 
    L_000e: box !!T
    L_0013: callvirt instance void WindowsFormsApplication1.IBar::Hidden()
Run Code Online (Sandbox Code Playgroud)

    L_000d: ldarga.s foo
    L_000f: constrained !!T
    L_0015: callvirt instance void WindowsFormsApplication1.IBar::Hidden()
Run Code Online (Sandbox Code Playgroud)

如果T是值类型,则会导致foo装入CallHidden1但不装入CallHidden2.但是,由于Foo是一个类,因此T派生的任何类型Foo都不是值类型,因此行为将是相同的.


Luc*_*ero 1

是的,有一点点,因为第二个指定必须实现接口,如果Foo以后更改为不实现,这可能会变得很重要IBar

CallHidden2<>这将使其不适合在编译时保持有效的同时使用(如果不再由 实现,CallHidden1<>则在运行时会失败)。IBarFoo

因此,如果它们位于不同的程序集中,不同的元数据将会产生影响。然而,执行的 IL 即使不相同,也将非常相似。