14

インターフェイス型制約を持つジェネリック メソッド内の明示的な C# インターフェイス呼び出しが常に基本実装を呼び出すのはなぜですか?

たとえば、次のコードを考えてみましょう。

public interface IBase
{
    string Method();
}

public interface IDerived : IBase
{
    new string Method();
}

public class Foo : IDerived
{
    string IBase.Method()
    {
        return "IBase.Method";
    }

    string IDerived.Method()
    {
        return "IDerived.Method";
    }
}

static class Program
{
    static void Main()
    {
        IDerived foo = new Foo();
        Console.WriteLine(foo.Method());
        Console.WriteLine(GenericMethod<IDerived>(foo));
    }

    private static string GenericMethod<T>(object foo) where T : class, IBase
    {
        return (foo as T).Method();
    }
}

このコードは次を出力します。

IDerived.Method
IBase.Method

予想されるものの代わりに:

IDerived.Method
IDerived.Method

実行時に決定された型の隠された、より派生した明示的なインターフェイス実装を呼び出す方法は (リフレクションを除いて) ないようです。

編集:明確にするために、上記の GenericMethod 呼び出しで check が true と評価される場合、次のようになります。

if (typeof(T) == typeof(IDerived))

したがって、答えは、「where T : class, IBase」というジェネリック型の制約により、T が常に IBase として扱われるということではありません。

4

2 に答える 2

1

まだ十分な評判がないため、コメントではできませんが、カイルの回答に追加します...

私はこれが言っていると思います:

private static string GenericMethod<T>(T foo) where T : class, IBase
{
    return foo.Method() + " "  + typeof(T) + " " + typeof(Foo);
}

オブジェクトを削除し、パラメーターを T にすると、as-cast は不要になり、IBase.Method が呼び出されます。

これはすべて、C# 仕様の4.4.4 Satisfying Constraintsが直接の原因であると確信しています。

この点で、C# ジェネリックは C++ テンプレートのようには動作しません。

于 2016-07-25T15:04:21.467 に答える