4

重複の可能性:
C# は戻り型の共分散をサポートしていますか?
この方法でインターフェイスを実装できないのはなぜですか?

次の点を考慮してください。

public interface IAnimal {
}

public class Animal : IAnimal {
}

public interface ICage {
     IAnimal SomeAnimal {get;}
}

public class Cage : ICage{
     public Animal SomeAnimal { get; set; }
}

IEnumerable の共分散と反分散に関する多くの資料を読みましたが、上記のコードを機能させる方法がわかりません。「Cage はインターフェイス メンバー IAnimal を実装していません」というエラーが表示されます。IAnimal よりもさらに定義された Animal を定義したので、共分散が私の世話をする必要があるようです。

私は何が欠けていますか?前もって感謝します。

4

4 に答える 4

6

これは現在 C# では不可能です。

理論的には、言語設計者がそれを追加することは可能ですが、[まだ]行っていません。C# の潜在的な将来のバージョンに追加することを決定する場合としない場合があります。

おそらく最善の回避策は次のとおりです。

public class Cage : ICage
{
    public Animal SomeAnimal { get; set; }

    IAnimal ICage.SomeAnimal
    {
        get { return SomeAnimal }
    }
}
于 2012-12-27T15:55:08.570 に答える
2

共分散を取得するには、次のようなものが必要です。

public interface IAnimal {
}

public class Lion : IAnimal {}
public class Sheep : IAnimal {}

// note the "out" on the T type parameter
public interface ICage<out T> where T:IAnimal {
     T SomeAnimal {get;}
}

public class Cage<T> : ICage<T> where T:IAnimal {
     public T SomeAnimal { get; set; }
}

これを行うことができます:

// without covariance on ICage you can't assign a 'Cage<Sheep>' to 'ICage<IAnimal>'
ICage<IAnimal> sheeps = new Cage<Sheep>() {SomeAnimal=new Sheep()};
ICage<IAnimal> lions = new Cage<Lion>() {SomeAnimal=new Lion()};

Cage<IAnimals>またはこれ( CagesofSheepsとCagesofLionsの両方で異種リストを作成する)。これは同等ですが、おそらくより有用な例です。

// without covariance on ICage it errors: cannot convert from 'Cage<Sheep>' to 'ICage<IAnimal>'
var zoo = new List<ICage<IAnimal>>{
     new Cage<Sheep> {SomeAnimal=new Sheep()},
     new Cage<Lion> {SomeAnimal=new Lion()},
};

out宣言からを削除しようとするICageと、違いがわかります。

于 2012-12-27T16:08:35.663 に答える
2
public interface IAnimal {
}

public class Animal : IAnimal {
}

public interface ICage {
     IAnimal SomeAnimal {get;}
}

public class Cage : ICage{
     public Animal SomeAnimal { get; set; }
}

public class AnotherAnimal : IAnimal {
}

Cage c = new Cage();
ICage ic = (ICage)c;
ic.Animal = new AnotherAnimal();

AnotherAnimalこれは を実装しているため無効ですIAnimalが、 ではありませんAnimal

編集

上記は、インターフェースでセッターが定義されている場合にのみ関連します。存在しないため、ここでの適切な答えは、C# では目的の機能を実現できないということです。これは言語に含まれていない機能です。

于 2012-12-27T16:00:21.797 に答える
2

ここで同じ質問をしたことに対する Eric Lippert からの引用: Why can't I implement an Interface this way?

C# は、インターフェイスの実装または仮想メソッドのオーバーライドを目的とした戻り値の型の共変性をサポートしていません。詳細については、この質問を参照してください。

C# は戻り値の型の共分散をサポートしていますか?

C# は、C# 4 の時点で、型引数の参照型で構築されたインターフェイスとデリゲート型の一般的な共変性と反変性をサポートしています。

また、C# は、参照型を返すメソッドを、戻り値の型が互換性のある参照型であるデリゲート型に変換するときに、戻り値の型の共分散をサポートします。(同様に、パラメーター型の反変性もサポートしています。)

このテーマに興味がある場合は、C# でサポートされているバリアンスとサポートされていないバリアンスのさまざまなバージョンについて説明した多数の記事を書いています。見る

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/

詳細については。

于 2012-12-27T15:55:11.710 に答える