1

List<T>type からいくつかのリストを取得した場合MyClass、たとえばList<List<MyClass>>MyClassからの親クラスですMyClassB。なぜ私は次のことができないのですか?

List<List<MyClass>> allLists = new List<List<MyClass>>();

List<MyClassB> myList = new List<MyClassB>();
myList.Add(new MyClassB());

//And now the point which dont work
allLists.Add(myList);

私が言うことができる方法を実装する場合SomeClass<T> ... where T : MyClass、私のリストの問題に似たようなものはありますか?

任意の子クラスのリストを第 1 レベルのリストに追加できるようにするには?

4

8 に答える 8

9
class Animal {}
class Tiger : Animal {}
class Giraffe : Animal {}
...
List<Giraffe> giraffes = new List<Giraffe>();
List<List<Animal>> lists = new List<List<Animal>>();
lists.Add(giraffes); // Illegal!

あなたの質問は、「なぜそれが違法なのですか?」答えは次のとおりです。それが合法であると仮定して、先に進みましょう...

List<Animal> animals = lists[0]; // Obviously typesafe.
animals.Add(new Tiger()); // Obviously typesafe

そして、キリンのリストにトラを追加しました。

後の 2 つの手順は明らかに型安全なので、型安全にできない場所はAdd(giraffes).

現在、C# 4 の時点で、これは機能します。

List<IEnumerable<Animal>> lists = new List<IEnumerable<Animal>>();
lists.Add(giraffes);

なぜそれが合法なのですか?AddにはメソッドがないためIEnumerable<T>

IEnumerable<Animal> animals = lists[0];

を介してのみアクセスしている場合、トラをキリンのリストに入れる方法がないため、型安全性に違反することはできませんIEnumerable<T>

ところで、ほぼ毎日誰かがこの質問をします。"C# covariance and contravariance" を Web 検索すると、より多くの情報が得られます。

于 2013-03-21T14:41:22.473 に答える
8

それができない理由は次のとおりですallLists.Add(myList)。うまくいったと想像してください。次に、コンパイラはそれallLists[0]が であることを認識するList<MyClass>ため、次のように記述しても問題ありません。

allLists[0].Add(new MyClassX());

は実際allLists[0]にはList<MyClassB>. MyClassXオブジェクトを保持することはできません。

が になるようにコードを変更するmyListList<MyClass>、コードは機能します。

List<MyClass> myList = new List<MyClass>();
myList.Add(new MyClassB()); // This works, because MyClassB extends MyClass
allLists.Add(myList); // This works, too
于 2013-03-21T14:39:01.953 に答える
2

内部コレクションとして、派生クラスを許可するインターフェイス(共変インターフェイスと呼ばれる)を使用する必要があります。

var allLists = new List<IEnumerable<MyClass>>();
于 2013-03-21T14:39:51.990 に答える
0

問題は、AllListsがMyClassのリストを含むように強く型付けされていることです。MyListは、MyClassBのインスタンスを含むように強く型付けされています。

ListをList>に保存することはできますが、現在のコードには型の不一致があります。

于 2013-03-21T14:40:34.107 に答える
0

これで問題が修正されます。

List<MyClass> myList = new List<MyClass>();
于 2013-03-21T14:40:39.850 に答える
0

MyClassB は MyClass のサブタイプですが、List が List のサブタイプであるとは限りません。あなたが尋ねたい質問は、List が T と共変でない理由です (これにより、List は、T が Y のサブタイプである List のサブタイプになります。共分散と反分散という用語を調べてください。

答えは 2 つあります。まず、リストは、C# が共変性と反変性を実装する前に実装されました。しかし、最も重要なことは、T が "out" 型の場合にのみ共変になるということです。リストに物を押し込むことができるので、アウトタイプではありません。IEnumerable は T 型のオブジェクトのみを発行します。したがって、共変になる可能性があります。

于 2013-03-21T14:45:54.633 に答える
0
List<List<MyClass>> allLists = new List<List<MyClass>>();

追加するリストは同じタイプではありません。あなたはこのようにすることができます:

interface IMyClass
{
    //some properties
}

すべての子クラスは IMyClass から継承する必要があります。すると、このようなリストになります。

List<List<IMyClass>> allLists = new List<List<IMyClass>>();
于 2013-03-21T14:37:47.800 に答える
0

MyClass が MyClassB の親であることをコンパイラに伝える必要があります。キーワードに関するこの記事whereは、さらに役立つ場合があります

于 2013-03-21T14:41:05.270 に答える