2

Foo<T>クラスBar<U>Bat<T>派生 元の汎用基本クラスがあります。Uから派生しTます。UBat と Bar は同様の実装ですが、タイプの値を異なる方法で処理する必要があるいくつかの場所のみが異なります。

には、型の引数を取り、またはオブジェクトを作成Fooするファクトリ メソッドがあります。おおよそ次のようになります。CreateTBarBat

public static IFoo<T> Create(T input) {
  if (input.TypeIdentifier == Types.Bar) {// exemplary type check
    // input is of or derives from `U`
    // return a Bar<U>
  } else 
    return new Bat(input);
}

// usage:
U myU = new ClassThatDerivesFromU();
T myT = new ClassThatDerivesFromT(CouldBe.Of(Type.U));
var myFoo1 = Create(myU); // of type IFoo<U>
var myFoo2 = Create(myT); // of type IFoo<T>

Tは ではないため、オブジェクトUをインスタンス化できません。Bar

考えられる解決策の1つは次のとおりです。

public static U To<T, U>(T input) where U : T {
  return input as U;
}

// to create Bar:
new Bar(To<T, U>(input));

ただし、これは非常にハックであり、構造体では使用できません (この場合、継承のためにとにかく構造体にすることはできませんが、たとえばaまたは aにU応じてメソッドを呼び出したい別のケースがあります)。Tstructclass

C++ では、このようなシナリオは、メソッドの複数のオーバーロードに異なる型制約を指定することで解決できます (iirc) Create。コンパイラは型をチェックしT、適切なメソッドを選択します (UまたはT型制約として)。

C# に同様の組み込みソリューションがあることは知りませんが、代わりに使用できる洗練された回避策があるのではないでしょうか? (反射は明白な答えですが、オプションではありません)

4

1 に答える 1

0

はい、インターフェイスを使用する場合は一般的な差異が許可されます。IFoo 内でジェネリック型パラメーターを宣言して、(使用法に応じて) 共変または反変のいずれかにすることができます。より派生した型を使用する場合は、その型Tは反変でなければならず、IFoo は次のように宣言できます。

interface IFoo<in T> { ... }

C# のジェネリックと差異の詳細については、この MSDN ページを参照してください。

アップデート

IFoo<U>anがIFoo<T>ifであるという条件U : T(たとえば、IFoo のジェネリック型が反変である) を取得したら、create メソッド内で自由に安全にキャストできます。

return (IFoo<T>)((object)new Bar<U>());
于 2012-12-11T08:36:43.320 に答える