0

次のキャストで少し問題が発生しています。

    class A 
    { 
    }

    class B : A 
    {
    }

    class C<T> where T : A
    {
        protected T property { get; set; }
    }

    class D : C<B> 
    {
    }

    class MainClass
    {
        public static void Main (string[] args)
        {
            C<A> x = new D();
            // Error CS0029: Cannot implicitly convert type `SampleApp.D' to `SampleApp.C<SampleApp.A>' (CS0029) (SampleApp)
        }
    }

、、を実装するDよりも幅が広いため、なぜこれが失敗するのかわかりません。回避策はありますか?C<A>C<B>B : A

4

3 に答える 3

2

C# 4.0 を使用できる場合は、次のコードを記述できます。

class A { }
class B : A {}

interface IC<out T> {}
class C<T> :IC<T> where T : A { protected T property { get; set; }  }

class D : C<B> {}

class MainClass {
    public static void Main()
    {
        IC<A> x = new D();
    }
}
于 2012-11-09T22:34:37.927 に答える
1

、、、およびのクラスAnimalに名前を付けましょう。ABarkerBDogD

実際C<Animal>にはより広いですDog : C<Barker>MeタイプTと割り当ての可能なパブリックプロパティがあると仮定します。

C<Animal> a = new Dog();
a.Me = Elephant; // where Elephant inherited from Animal

おっと!Dogでパラメータ化されBarkerます。象の吠えを見たことがありますか?

C<Barker>より派生型の引数でインスタンス化されたクラスを、より派生型の引数でインスタンス化されたオブジェクトに割り当てることができるように、共変インターフェイスを宣言する必要がありますC<Animal>。@NickWが提案したように、空のインターフェイスを使用できますが、そのインターフェイスのインスタンスで何かを行うことはできません(空です!)。だから、そのようなことをしましょう:

interface IC<out T>
    where T : Animal
{
    IEnumerable<T> Parents(); // IEnumerable is covariant
    T Me { get; } // no setter
}

class C<T> : IC<T>
    where T: Animal
{
    // implementation
}

class D : C<Barker>
{
    // implementation
}

上記のシナリオはまだ不可能ですが、今はできます

IC<Animal> a = new Dog();
foreach(var parent in a.Parents)
     Console.WriteLine(parent);

Console.WriteLine(a.Me);
于 2012-11-09T22:28:10.977 に答える
-1

Genericsは実際にはテンプレートであり、それらを使用して実行したいように動作しないため、これを行うことはできません。これでお見せしましょう:

あなたが言うとき、それはのによる"C<A>"ジェネリッククラスを意味します。しかし、あなたが言うとき、それは正確に意味します!"parameter""A""D""D"

したがって、DはAのパラメーターによるジェネリッククラスと等しくありません。両方のタイプのToString関数の結果で簡単にわかるように(typeofを使用して)。

それが役に立てば幸い

乾杯

于 2012-11-09T22:22:13.620 に答える