一般的な制約にもかかわらずC#型の変換エラー
-
06-07-2019 - |
質問
クラスPの型パラメーターTに<!> quot; A <!> quot;から継承する必要がある一般的な制約がある場合、最初の呼び出しは成功しますが、2番目の呼び出しは、コメント:
abstract class A { }
static class S
{
public static void DoFirst(A argument) { }
public static void DoSecond(ICollection<A> argument) { }
}
static class P<T>
where T : A, new()
{
static void Do()
{
S.DoFirst(new T()); // this call is OK
S.DoSecond(new List<T>()); // this call won't compile with:
/* cannot convert from 'System.Collections.Generic.List<T>'
to 'System.Collections.Generic.ICollection<A>' */
}
}
List<T>
が実際にICollection<A>
であることを一般的な制約で保証すべきではないか
解決
これは、C#にジェネリック型(C#配列の共分散をサポートします 。 C#4は、この機能をインターフェイスタイプに追加し、いくつかのBCLインターフェイスタイプも更新して同様にサポートします。
この記事では、I <!>#8217;カバーを試みます C#4.0の革新。一つ 新機能は共分散であり、 型パラメーターの反分散 汎用デリゲートによってサポートされるようになりました および汎用インターフェース。まずは<!>#8217; s これらの単語の意味を確認してください:)
他のヒント
制約は問題に影響しません。問題は、ICollectionを必要とするパラメーターでリストを渡すことです。C#は共分散をサポートしていないため、リストを明示的にICollectionにキャストする必要があります。
S.DoSecond((ICollection<A>) new List<T>()); // this call will be happy
DoSecondのパラメーターをICollection <!> lt; A <!> gt;型として強く入力しました。 TはタイプAであるにもかかわらず、コンパイル時にList <!> lt; T <!> gt;の間に暗黙的キャストはありません。およびICollection <!> lt; A <!> gt;。リストを作成してICollection <!> lt; A <!> gt;にキャストする必要があります。 DoSecondを呼び出すとき、またはDoSecond自体をジェネリックメソッドにするとき。
注:このタイプの暗黙のキャストは、C#4.0でサポートされる必要があります。これにより、C#3.0が提供するものよりも大幅に改善された相互/共分散が提供されます。