2 Stimmen

C# - wie man eine geerbte generische Sammlung von einer Fabrik-Methode erstellen

Ich versuche, eine Factory-Methode zu schreiben, die eine abgeleitete Instanz einer abstrakten generischen Auflistungsklasse erstellen wird. Hier sind die Basisklassen ...

abstract class ItemBase { }

abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }

...und ihre abgeleiteten Klassen ...

class Item : ItemBase { }

class ItemCollection : CollectionBase<Item> {}

Nun möchte ich eine Factory-Methode, die eine ItemCollection erstellt. Beachten Sie jedoch, dass die abgeleiteten Klassen Item und ItemCollection der Klasse, die diese Fabrikmethode enthält, unbekannt sind. Ich stelle mir das folgendermaßen vor ...

static T CreateItemCollection<T>() where T : CollectionBase<ItemBase>, new()
{
    return new T();
}

... und ich stelle mir vor, es so zu beschwören ...

var collection = CreateItemCollection<ItemCollection>();

Aber die Factory-Methode lässt sich nicht kompilieren, weil ItemBase einen parameterlosen Konstruktor haben muss. Und der Aufruf weigert sich zu glauben, dass ItemCollection wird abgeleitet von CollectionBase<ItemBase> .

Kann mir bitte jemand die richtige Richtung weisen? Danke!

6voto

Jon Skeet Punkte 1325502

ItemCollection ist nicht abgeleitet von CollectionBase<ItemBase> aufgrund der generischen Invarianz. Schließlich können Sie eine ItemBase zu einer CollectionBase<ItemBase> - aber das wollen Sie nicht für Ihre ItemCollection !

Sie müssen die Methode in zwei Typparametern generisch machen:

static T CreateItemCollection<TCollection, TItem>()
    where TCollection : CollectionBase<TItem>, new()
    where TItem : ItemBase
{
    return new TCollection();
}

Nur der Typ collection benötigt einen parameterlosen Konstruktor. Sie würden diesen mit aufrufen:

var collection = CreateItemCollection<ItemCollection, Item>();

3voto

JaredPar Punkte 699699

Das Problem dabei ist, dass generische Constraints in C# 3.0 keinen Spielraum in Bezug auf die Varianz haben. Der Abgleich ist stattdessen ziemlich streng. Da ItemCollection abgeleitet ist von CollectionBase<Item> es wird nicht als abgeleitet von CollectionBase<ItemBase> auch wenn die Typen möglicherweise erscheinen kompatibel zu sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X