3

クラス P の型パラメーター T に「A から継承する必要がある」という一般的な制約がある場合、最初の呼び出しは成功するが、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>か?

4

3 に答える 3

7

これは、ジェネリック型に対する C# の共分散の欠如の例です(C#配列の共分散をサポートしています)。C# 4 では、インターフェイス タイプにこの機能が追加され、いくつかの BCL インターフェイス タイプもサポートされるように更新されます。

C# 4.0: 共分散と反分散を参照してください。

この記事では、C# 4.0 のイノベーションの 1 つを取り上げます。新機能の 1 つは、型パラメーターの共変性と反変性であり、ジェネリック デリゲートとジェネリック インターフェイスでサポートされるようになりました。まず、これらの単語の意味を見てみましょう:)

于 2009-07-31T19:54:46.303 に答える
0

制約は問題に影響しません。問題は、ICollection を必要とするパラメーターで List を渡していることです。C# は共分散をサポートしていないため、リストを ICollection に明示的にキャストする必要があります。

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy
于 2009-07-31T19:57:34.487 に答える
0

DoSecond のパラメーターを ICollection<A> 型として厳密に型指定しました。T は A 型ですが、コンパイル時にはList<T> と ICollection<A> の間に暗黙的なキャストはありません。DoSecond を呼び出すときに、リストを作成して ICollection<A> にキャストするか、DoSecond 自体をジェネリック メソッドにする必要があります。

注: このタイプの暗黙的なキャストは、C# 4.0 でサポートされる必要があります。これにより、C# 3.0 が提供するものよりもはるかに改善された共分散/反変性が提供されます。

于 2009-07-31T19:57:52.803 に答える