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) に違いはありますか? where T : Foo と where T : Foo, IBar (Foo が IBar を実装している場合) の間に、明示的に実装されたインターフェイスメンバーにアクセスする際の他の違いはありますか?

4

2 に答える 2

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はクラスであるため、からT派生しFooた型は値型にはならず、動作は同じになります。

于 2010-02-05T16:55:04.960 に答える
1

はい、少しだけです。2番目はインターフェイスを実装する必要があることを指定しているためです。Fooこれは、後で実装されないように変更された場合に重要になる可能性がありますIBar

CallHidden2<>そのため、コンパイル時に有効なままで使用するのは不適切になります(によって実装されなくなったCallHidden1<>場合、実行時に失敗します)。IBarFoo

したがって、それらが別々のアセンブリにある場合、異なるメタデータが違いを生みます。ただし、実行されるILは、同じではないにしても、かなり似ています。

于 2010-02-05T16:34:27.850 に答える