Generische Klassen (C#-Programmierhandbuch)Generic Classes (C# Programming Guide)

Generische Klassen kapseln Operationen, die nicht spezifisch für einen bestimmten Datentyp sind.Generic classes encapsulate operations that are not specific to a particular data type. Generische Klassen werden am häufigsten bei Auflistungen verwendet, z.B. bei verknüpften Listen, Hashtabellen, Stapeln, Warteschlangen, Strukturen usw.The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on. Vorgänge wie das Hinzufügen oder Entfernen von Elementen aus der Auflistung werden nahezu auf die gleiche Art und Weise ausgeführt, unabhängig vom Typ der gespeicherten Daten.Operations such as adding and removing items from the collection are performed in basically the same way regardless of the type of data being stored.

Für die meisten Szenarios, die Auflistungsklassen erfordern, wird empfohlen, die in der Klassenbibliothek von .NET bereitgestellten Auflistungsklassen zu verwenden.For most scenarios that require collection classes, the recommended approach is to use the ones provided in the .NET class library. Weitere Informationen zur Verwendung dieser Klassen finden Sie unter Generic Collections in .NET (Generische Auflistungen in .NET).For more information about using these classes, see Generic Collections in .NET.

In der Regel erstellen Sie generische Klassen, indem Sie von einer vorhandenen konkreten Klasse ausgehen und Typen in Typparameter ändern (einen nach dem anderen), bis das optimale Verhältnis zwischen Verallgemeinerung und Verwendbarkeit gefunden ist.Typically, you create generic classes by starting with an existing concrete class, and changing types into type parameters one at a time until you reach the optimal balance of generalization and usability. Wenn Sie eigene generische Klassen erstellen möchten, sollten Sie die folgenden wichtigen Aspekte beachten:When creating your own generic classes, important considerations include the following:

  • Welche Typen sollen in Typparameter verallgemeinert werden.Which types to generalize into type parameters.

    Im Allgemeinen gilt: Je mehr Typen Sie parametrisieren können, umso flexibler und besser wiederverwendbar ist Ihr Code.As a rule, the more types you can parameterize, the more flexible and reusable your code becomes. Jedoch kann ein Zuviel an Verallgemeinerung zu Code führen, der von anderen Entwicklern nur schwer gelesen oder verstanden wird.However, too much generalization can create code that is difficult for other developers to read or understand.

  • Welche Einschränkungen sollen ggf. auf die Typparameter angewendet werden (siehe Constraints on Type Parameters (Einschränkungen für Typparameter)).What constraints, if any, to apply to the type parameters (See Constraints on Type Parameters).

    Es empfiehlt sich, alle Einschränkungen anzuwenden, die maximal möglich sind, und bei denen Sie dennoch sämtliche Typen, die Sie behandeln müssen, auch behandeln können.A good rule is to apply the maximum constraints possible that will still let you handle the types you must handle. Wenn Sie zum Beispiel wissen, dass die generische Klasse nur mit Referenztypen verwendet werden soll, dann können Sie die Klasseneinschränkung anwenden.For example, if you know that your generic class is intended for use only with reference types, apply the class constraint. Dadurch wird verhindert, dass die Klasse unbeabsichtigt mit Werttypen verwendet wird. Gleichzeitig können Sie den Operator as für T verwenden und nach NULL-Werten suchen.That will prevent unintended use of your class with value types, and will enable you to use the as operator on T, and check for null values.

  • Ob das generische Verhalten in Basisklassen und Unterklassen zerlegt werden soll.Whether to factor generic behavior into base classes and subclasses.

    Da generische Klassen als Basisklassen dienen können, sind hier beim Entwurf die gleichen Aspekte zu berücksichtigen wie bei nicht generischen Klassen.Because generic classes can serve as base classes, the same design considerations apply here as with non-generic classes. Weitere Informationen bieten die Regeln zum Erben von generischen Basisklassen weiter unten in diesem Thema.See the rules about inheriting from generic base classes later in this topic.

  • Ob eine oder mehrere generische Schnittstellen implementiert werden soll.Whether to implement one or more generic interfaces.

    Wenn Sie beispielsweise eine Klasse entwerfen, die zum Erstellen von Elementen in einer generisch basierten Auflistung verwendet wird, müssen Sie unter Umständen eine Schnittstelle implementieren, z.B. IComparable<T>, wobei T der Typ Ihrer Klasse ist.For example, if you are designing a class that will be used to create items in a generics-based collection, you may have to implement an interface such as IComparable<T> where T is the type of your class.

Ein Beispiel für eine einfache generische Klasse finden Sie unter Introduction to Generics (Einführung in Generika).For an example of a simple generic class, see Introduction to Generics.

Die Regeln für Einschränkungen und Typparameter haben eine Reihe von Auswirkungen auf das Verhalten einer generischen Klasse, besonders im Hinblick auf Vererbung und Zugriff der Member.The rules for type parameters and constraints have several implications for generic class behavior, especially regarding inheritance and member accessibility. Bevor Sie fortfahren, sollten Sie einige Begriffe verstehen.Before proceeding, you should understand some terms. Bei einer generischen Klasse kann der Clientcode Node<T>, auf die Klasse verweisen, indem er ein Typargument angibt, um einen geschlossenen konstruierten Typ (Node<int>) zu erstellen.For a generic class Node<T>, client code can reference the class either by specifying a type argument, to create a closed constructed type (Node<int>). Die Alternative besteht darin, den Typparameter nicht anzugeben, z.B. wenn Sie eine generische Basisklasse angeben, um einen offenen konstruierten Typ (Node<T>) zu erstellen.Alternatively, it can leave the type parameter unspecified, for example when you specify a generic base class, to create an open constructed type (Node<T>). Generische Klassen können von konkreten, geschlossenen konstruierten oder offenen konstruierten Basisklassen erben:Generic classes can inherit from concrete, closed constructed, or open constructed base classes:

class BaseNode { }
class BaseNodeGeneric<T> { }

// concrete type
class NodeConcrete<T> : BaseNode { }

//closed constructed type
class NodeClosed<T> : BaseNodeGeneric<int> { }

//open constructed type 
class NodeOpen<T> : BaseNodeGeneric<T> { }

Nicht generische, also konkrete Klassen können von geschlossenen konstruierten Basisklassen erben, aber nicht von offenen konstruierten Klassen oder Typparametern, denn während der Laufzeit ist es für den Clientcode nicht möglich, das erforderliche Typargument bereitzustellen, das zum Instanziieren der Basisklasse benötigt wird.Non-generic, in other words, concrete, classes can inherit from closed constructed base classes, but not from open constructed classes or from type parameters because there is no way at run time for client code to supply the type argument required to instantiate the base class.

//No error
class Node1 : BaseNodeGeneric<int> { }

//Generates an error
//class Node2 : BaseNodeGeneric<T> {}

//Generates an error
//class Node3 : T {}

Generische Klassen, die von offenen konstruierten Typen erben, müssen für sämtliche Basisklassen-Typparameter, die von der erbenden Klasse nicht verwendet werden, Typargumente bereitstellen. Der folgende Code stellt ein Beispiel dafür dar:Generic classes that inherit from open constructed types must supply type arguments for any base class type parameters that are not shared by the inheriting class, as demonstrated in the following code:

class BaseNodeMultiple<T, U> { }

//No error
class Node4<T> : BaseNodeMultiple<T, int> { }

//No error
class Node5<T, U> : BaseNodeMultiple<T, U> { }

//Generates an error
//class Node6<T> : BaseNodeMultiple<T, U> {} 

Generische Klassen, die von offenen konstruierten Typen erben, müssen Einschränkungen angeben, die den Einschränkungen des Basistyps übergeordnet sind oder diese implizieren:Generic classes that inherit from open constructed types must specify constraints that are a superset of, or imply, the constraints on the base type:

class NodeItem<T> where T : System.IComparable<T>, new() { }
class SpecialNodeItem<T> : NodeItem<T> where T : System.IComparable<T>, new() { }

Generische Typen können mehrere Typparameter und Einschränkungen wie folgt verwenden:Generic types can use multiple type parameters and constraints, as follows:

class SuperKeyType<K, V, U>
    where U : System.IComparable<U>
    where V : new()
{ }

Offene konstruierte und geschlossene konstruierte Typen können als Methodenparameter verwendet werden:Open constructed and closed constructed types can be used as method parameters:

void Swap<T>(List<T> list1, List<T> list2)
{
    //code to swap items
}

void Swap(List<int> list1, List<int> list2)
{
    //code to swap items
}

Wenn eine generische Klasse eine Schnittstelle implementiert, können alle Instanzen dieser Klasse in diese Schnittstelle umgewandelt werden.If a generic class implements an interface, all instances of that class can be cast to that interface.

Generische Klassen sind unveränderlich.Generic classes are invariant. Wenn also ein Eingabeparameter eine List<BaseClass> angibt, wird Ihnen ein Kompilierungsfehler angezeigt, falls Sie versuchen, eine List<DerivedClass> bereitzustellen.In other words, if an input parameter specifies a List<BaseClass>, you will get a compile-time error if you try to provide a List<DerivedClass>.

Siehe auchSee Also