45

そのようなインターフェースと具体的な実装があるとしましょう

public interface IMyInterface<T>
{
    T My();
}

public class MyConcrete : IMyInterface<string>
{
    public string My()
    {
        return string.Empty;
    }
}

の MyConcrete 実装を作成するとstrings、 の具体的な実装をもう 1 つ持つことができますint。そして、それは大丈夫です。しかし、同じことをしたいのですが、ジェネリックメソッドを使用しているとしましょう。

public interface IMyInterface2
{
    T My<T>();
}

public class MyConcrete2 : IMyInterface2
{
    public string My<string>()
    {
        throw new NotImplementedException();
    }
}

だから私は同じを持っていIMyInterface2ますが、これは によって一般的な動作を定義しますT My<T>()。私の具体的なクラスではMy、動作を実装したいのですが、具体的なデータ型については - string. しかし、C# ではそれができません。

私の質問は、なぜ私はそれができないのですか? MyInterface<T>つまり、この時点でasの具体的な実装を作成MyClass : MyInterface<string>してジェネリック性を停止できる場合、ジェネリック メソッドでそれを実行できないのはなぜT My<T>()ですか?

4

4 に答える 4

43

ジェネリック メソッドの実装もジェネリックである必要があるため、次のようにする必要があります。

public class MyConcrete2 : IMyInterface2
{
    public T My<T>()
    {
        throw new NotImplementedException();
    }
}

なぜMy<string>()ここでできないのですか?インターフェイス契約にはメソッドが必要なため、任意の型パラメーターで呼び出すことができ、その契約Tを満たす必要があります。

この時点で一般性を止められないのはなぜですか?次のような状況が発生するためです。

クラス宣言:

public interface IMyInterface2
{
    T My<T>(T value);
}

public class MyClass21 : IMyInterface2
{
    public string My<string>(string value) { return value; }
}

public class MyClass22 : IMyInterface2
{
    public int My<int>(int value) { return value; }
}

使用法:

var item1 = new MyClass21();
var item2 = new MyClass22();

// they both implement IMyInterface2, so we can put them into list
var list = new List<IMyInterface2>();
list.Add(item1);
list.Add(item2);

// iterate the list and call My method
foreach(IMyInterface2 item in list)
{
    // item is IMyInterface2, so we have My<T>() method. Choose T to be int and call with value 2:
    item.My<int>(2);

    // how would it work with item1, which has My<string> implemented?
}
于 2013-07-11T14:34:21.610 に答える
5

あなたのインターフェースはジェネリックメソッドT My<T>()を宣言していますが、あなたの実装はその特定のシグネチャを持つ関数を実装していません。

目的を達成するには、最初の例で、代わりに T ジェネリック パラメーターをインターフェイスに提供する必要があります。

public interface IMyInterface2<T>
{
        T My();
}

public class MyConcrete2 : IMyInterface2<string>
{
    public string My()
    {
        throw new NotImplementedException();
    }
}
于 2013-07-11T14:38:25.393 に答える
1

あなたのソリューションは、2 つの理由で機能しません。

まず、インターフェースはコントラクトです。実装するときは、ジェネリック型パラメーターを取り、その型を返すという IMyInterface2名前の関数を実装することを保証します。これはしません。MyMyConcrete2

第 2 に、C# ジェネリックでは、型パラメーターの特殊化は一切許可されません。(C# でこれがサポートされていることを願っています。) これは、例がコンパイルされる C++ テンプレートでは一般的なことですMyConcrete2Mystring.

于 2013-07-11T16:40:18.067 に答える