Explicitly implemented interface and generic constraint

雨燕双飞 提交于 2019-12-09 17:17:42

问题


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;
    }
}

Is there any difference (CallHidden1 vs. CallHidden2) is actual compiled code? Is there other differences between where T : Foo and where T : Foo, IBar (if Foo implements IBar) that in accessing explicitly implemented interface members ?


回答1:


The IL generated is slightly different:

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

vs.

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

If T were a value type, this would result in foo being boxed in CallHidden1 but not in CallHidden2. However, since Foo is a class, any type T derived from Foo will not be a value type, and thus the behavior will be identical.




回答2:


Yes, a tiny bit, since the second specifies that the interface must be implemented, which may become important if Foo is later changed so that it does not implement IBar.

That would make it unsuitable for being used in CallHidden2<> while remaining valid at compile time for CallHidden1<> (which would then fail at runtime if IBar is no longer being implemented by Foo).

So if they are in separate assemblies, the different metadata would make a difference. The executed IL will, however, be pretty similar if not the same.



来源:https://stackoverflow.com/questions/2208642/explicitly-implemented-interface-and-generic-constraint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!