显式实现的接口和通用约束

发布于 2024-08-20 05:44:42 字数 600 浏览 11 评论 0原文

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)吗? 在访问显式实现的接口成员方面, where T : Foo 和 where T : Foo, IBar (如果 Foo 实现了 IBar)之间还有其他区别吗?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月牙弯弯 2024-08-27 05:44:42

生成的 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 都不会是值类型,因此行为将是相同的。

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.

↙厌世 2024-08-27 05:44:42

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文