Eric Lippert は、彼のブログ投稿 ( http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx ) で、なぜ制約が適用されないのかを説明しています。これは、型の制約を変更するだけではメソッドをオーバーロードできないことを考えると理にかなっています。ただし、タイプを指定することなく、2 つのジェネリック型を使用してオブジェクトをインスタンス化する方法を見つけたいと思います。
与えられたタイプ:
public interface I<T>
{
Other<T> CreateOther();
}
public class C : I<string>
{
public Other<string> CreateOther()
{
return new Other<string>();
}
}
public class Other<T>
{
}
そして工場:
public static class Factory1
{
public static Tuple<T, Other<T1>> Create<T, T1>(T o) where T : I<T1>
{
return new Tuple<T, Other<T1>>(o, o.CreateOther());
}
}
次の目的のコードはコンパイルされません。
public void WontCompile()
{
C c = new C();
var v = Factory1.Create(c); // won't compile
}
エラー メッセージは「エラー CS0411: メソッド 'yo.Factory1.Create(T)' の型引数を使用法から推測できません。型引数を明示的に指定してください。」であり、これは Eric がブログで述べたことと一致しています。役職。
したがって、エラー メッセージが示すように、ジェネリック型引数を明示的に指定するだけです。
public void SpecifyAllTypes()
{
C c = new C();
var v = Factory1.Create<C, string>(c); // type is Tuple<C, Other<string>>
}
型引数を指定したくなく、型 C を保持する必要がない場合は、次のファクトリを使用できます。
public static class Factory2
{
public static Tuple<I<T1>, Other<T1>> CreateUntyped<T1>(I<T1> o)
{
return new Tuple<I<T1>, Other<T1>>(o, o.CreateOther());
}
}
次に指定します。
public void Untyped()
{
C c = new C();
var v = Factory2.CreateUntyped(c); // type is Tuple<I<string>, Other<string>>
}
ただし、返されるオブジェクトに型 C を保持し、型を指定したくありません。