Übersicht über Generics in C++/CLIOverview of Generics in C++/CLI

Generics sind parametrisierte Typen, die von der Common Language Runtime unterstützt werden.Generics are parameterized types supported by the common language runtime. Ein parametrisierter Typ ist ein Typ, der mit einem unbekannten, bei der Verwendung des Generics angegebenen Typparameter definiert ist.A parameterized type is a type that is defined with an unknown type parameter that is specified when the generic is used.

Warum Generics?Why Generics?

C++ unterstützt Vorlagen, und sowohl Vorlagen als auch Generics unterstützen parametrisierte Typen zum Erstellen typisierter Sammlungsklassen.C++ supports templates and both templates and generics support parameterized types to create typed collection classes. Allerdings bieten Vorlagen Parametrisierung während der Kompilierzeit.However, templates provide compile-time parameterization. Sie können nicht auf eine Assembly verweisen, die eine Vorlagendefinition enthält, und neue Spezialisierungen der Vorlage erstellen.You cannot reference an assembly containing a template definition and create new specializations of the template. Nach der Kompilierung sieht eine spezialisierte Vorlage wie jede andere Klasse oder Methode aus.Once compiled, a specialized template looks like any other class or method. Im Gegensatz dazu werden Generics in MSIL als parametrisierter Typ ausgegeben, den die Runtime als parametrisierten Typ kennt; Quellcode, der auf eine Assembly verweist, die einen generischen Typ enthält, kann Spezialisierungen des generischen Typs erstellen.In contrast, generics are emitted in MSIL as a parameterized type known by the runtime to be a parameterized type; source code that references an assembly containing a generic type can create specializations of the generic type. Weitere Informationen zum Vergleich von standardmäßigen C++-Vorlagen und Generics finden Sie unter Generics und Vorlagen (C++/CLI).For more information on the comparison of standard C++ templates and generics, see Generics and Templates (C++/CLI).

Generische Funktionen und TypenGeneric Functions and Types

Klassentypen können, solange sie verwaltete Typen sind, generisch sein.Class types, as long as they are managed types, may be generic. Ein Beispiel hierfür könnte eine List-Klasse sein.An example of this might be a List class. Der Typ eines Objekts in der Liste wäre der Typparameter.The type of an object in the list would be the type parameter. Wenn Sie eine List-Klasse für viele verschiedene Typen von Objekten benötigen würden, hätten Sie, als es die Generics noch nicht gab, vielleicht eine List verwendet, die System::Object als Elementtyp akzeptiert.If you needed a List class for many different types of objects, before generics you might have used a List that takes System::Object as the item type. Aber dies würde die Verwendung jedes Objekts (einschließlich Objekte des falschen Typs) in der Liste zulassen.But that would allow any object (including objects of the wrong type) to be used in the list. Eine solche Liste würde als nicht typisierte Sammlungsklasse bezeichnet.Such a list would be called an untyped collection class. Im besten Fall könnten Sie den Typ zur Laufzeit überprüfen und eine Ausnahme auslösen.At best, you could check the type at runtime and throw an exception. Sie hätten vielleicht auch eine Vorlage verwendet, die nach der Kompilierung in eine Assembly ihre generische Qualität verloren hätte.Or, you might have used a template, which would lose its generic quality once compiled into an assembly. Consumer Ihrer Assembly könnten nicht eigene Spezialisierungen der Vorlage erstellen.Consumers of your assembly could not create their own specializations of the template. Mit Generics können Sie typisierte Sammlungsklassen erstellen, z.B. List<int> („Int-Liste“) und List<double> („Double-Liste“), was einen Kompilierzeitfehler verursachen würde, wenn Sie versuchen würden, einen Typ zu platzieren, für dessen Akzeptanz in der typisierten Sammlung die Sammlung nicht ausgelegt ist.Generics allow you to create typed collection classes, say List<int> (read as "List of int") and List<double> ("List of double") which would generate a compile-time error if you tried to put a type that the collection was not designed to accept into the typed collection. Darüber hinaus bleiben diese Typen generisch, wenn sie kompiliert werden.In addition, these types remain generic after they are compiled.

Eine Beschreibung der Syntax von generischen Klassen finden Sie unter Generische Klassen (C++/CLI).A description of the syntax of generic classes may be found in Generic Classes (C++/CLI). Ein neuer Namespace, System.Collections.Generic, führt eine Reihe von parametrisierten Sammlungstypen inklusive Dictionary<TKey,TValue>, List<T> und LinkedList<T> ein.A new namespace, System.Collections.Generic, introduces a set of parameterized collection types including Dictionary<TKey,TValue>, List<T> and LinkedList<T>.

Sowohl Instanz- als auch statische Memberfunktionen, Delegaten und globale Funktionen können auch generisch sein.Both instance and static class member functions, delegates, and global functions may also be generic. Generische Funktionen können erforderlich sein, wenn die Parameter einer Funktion unbekannten Typs sind oder die Funktion selbst mit generischen Typen arbeiten muss.Generic functions may be necessary if the function's parameters are of an unknown type, or if the function itself must work with generic types. In vielen Fällen, in denen System::Object in der Vergangenheit vielleicht als Parameter für einen unbekannten Objekttyp verwendet wurde, könnte stattdessen ein generischer Typparameter verwendet werden, der typsichereren Code zulässt.In many cases where System::Object may have been used in the past as a parameter for an unknown object type, a generic type parameter may be used instead, allowing for more type-safe code. Zur Kompilierzeit würde jeder Versuch, einen Typ zu übergeben, für den die Funktion nicht entworfen wurde, als Fehler gekennzeichnet.Any attempt to pass in a type that the function was not designed for would be flagged as an error at compile time. Mithilfe von System::Object als Funktionsparameter würde die unbeabsichtigte Übergabe eines Objekts, für das die Funktion nicht vorgesehen ist, nicht erkannt werden, und Sie müssten den unbekannten Objekttyp im Funktionsrumpf in einen bestimmten Typ umwandeln und die Möglichkeit einer InvalidCastException berücksichtigen.Using System::Object as a function parameter, the inadvertent passing of an object that the function wasn't intended to deal with would not be detected, and you would have to cast the unknown object type to a specific type in the function body, and account for the possibility of an InvalidCastException. Mit einem Generic würde Code, der versucht, der Funktion ein Objekt zu übergeben, einen Typenkonflikt auslösen, sodass der Funktionsrumpf garantiert den richtigen Typ hat.With a generic, code attempting to pass an object to the function would cause a type conflict so the function body is guaranteed to have the correct type.

Die gleichen Vorteile gelten für Sammlungsklassen, die auf der Basis von Generics erstellt sind.The same benefits apply to collection classes built on generics. In der Vergangenheit hätten Sammlungsklassen System::Object zum Speichern von Elementen in einer Sammlung verwendet.Collection classes in the past would use System::Object to store elements in a collection. Das Einfügen von Objekten eines Typs, für den die Sammlung nicht vorgesehen ist, wurde nicht zur Kompilierzeit als Fehler gekennzeichnet, und oft auch sogar dann nicht, wenn die Objekte eingefügt wurden.Insertion of objects of a type that the collection was not designed for was not flagged at compile time, and often not even when the objects were inserted. In der Regel wird ein Objekt in einen anderen Typ umgewandelt, wenn in der Sammlung darauf zugegriffen wird.Usually, an object would be cast to some other type when it was accessed in the collection. Nur wenn bei der Umwandlung ein Fehler auftritt, würde der unerwartete Typ erkannt werden.Only when the cast failed would the unexpected type be detected. Generics lösen dieses Problem zur Kompilierzeit durch Erkennung von Code, der einen nicht mit dem Typparameter der generischen Sammlung übereinstimmenden Typ einfügt (oder implizit in diesen konvertiert).Generics solves this problem at compile time by detecting any code that inserts a type that doesn't match (or implicitly convert to) the type parameter of the generic collection.

Eine Beschreibung der Syntax finden Sie unter Generische Funktionen (C++/CLI).For a description of the syntax, see Generic Functions (C++/CLI).

Mit Generics verwendete TerminologieTerminology Used With Generics

TypparameterType Parameters

Eine generische Deklaration enthält einen oder mehrere unbekannte Typen, die Typparameter genannt werden.A generic declaration contains one or more unknown types known as type parameters. Typparametern wird ein Name zugewiesen, der innerhalb des Texts der generischen Deklaration für den Typ steht.Type parameters are given a name which stands for the type within the body of the generic declaration. Der Typparameter wird innerhalb des Texts der generischen Deklaration als Typ verwendet.The type parameter is used as a type within the body of the generic declaration. Die generische Deklaration für List<T> enthält den Typparameter "T".The generic declaration for List<T> contains the type parameter T.

TypargumenteType Arguments

Das Typargument ist der anstelle des Typparameters tatsächlich verwendete Typ, wenn das Generic für einen bestimmten Typ oder bestimmte Typen spezifiziert wird.The type argument is the actual type used in place of the type parameter when the generic is specialized for a specific type or types. Beispiel: int ist das Typargument in List<int>.For example, int is the type argument in List<int>. Werttypen und Typen von Handles sind die einzigen Typen, die in einem generischen Typargument zulässig sind.Value types and handle types are the only types allowed in as a generic type argument.

Konstruierter TypConstructed Type

Ein aus einem generischen Typ erstellter Typ wird als konstruierter Typ bezeichnet.A type constructed from a generic type is referred to as a constructed type. Ein nicht vollständig angegebener Typ wie z.B. List<T> ist ein offen konstruierter Typ; ein vollständig angegebener Typ wie z.B. List<double>, ist ein geschlossen konstruierter Typ oder spezialisierter Typ.A type not fully specified, such as List<T> is an open constructed type; a type fully specified, such as List<double>, is a closed constructed type or specialized type. Offen konstruierte Typen können in der Definition anderer generischer Typen oder Methoden verwendet werden und dürfen nicht vollständig angegeben werden, bis das einschließende Generic selbst angegeben ist.Open constructed types may be used in the definition of other generic types or methods and may not be fully specified until the enclosing generic is itself specified. Im Folgenden sehen Sie ein Beispiel für die Verwendung eines offen konstruierten Typs als Basisklasse für ein Generic:For example, the following is a use of an open constructed type as a base class for a generic:

// generics_overview.cpp
// compile with: /clr /c
generic <typename T>

ref class List {};

generic <typename T>

ref class Queue : public List<T> {};

EinschränkungConstraint

Eine Einschränkung ist eine Einschränkung für Typen, die als Typparameter verwendet werden können.A constraint is a restriction on the types that may be used as a type parameter. Beispielsweise könnte eine bestimmte generische Klasse nur Klassen akzeptieren, die von einer angegebenen Klasse erben oder eine angegebene Schnittstelle implementieren.For example, a given generic class could accept only classes that inherit from a specified class, or implement a specified interface. Weitere Informationen finden Sie unter Einschränkungen für generische Typparameter (C++/CLI).For more information, see Constraints on Generic Type Parameters (C++/CLI).

Verweistypen und WerttypenReference Types and Value Types

Handletypen und Werttypen können als Typargumente verwendet werden.Handles types and value types may be used as type arguments. In der generischen Definition, in der beide Typen verwendet werden können, ist die Syntax der von Verweistypen.In the generic definition, in which either type may be used, the syntax is that of reference types. Beispiel: Der ->-Operator wird verwendet, um auf Member des Typs des Typparameters zuzugreifen, und zwar unabhängig davon, ob der schließlich verwendete Typ ein Verweistyp oder ein Werttyp ist.For example, the -> operator is used to access members of the type of the type parameter whether or not the type eventually used is a reference type or a value type. Wenn ein Werttyp als Typargument verwendet wird, generiert die Runtime Code, der die Werttypen direkt ohne Boxing verwendet.When a value type is used as the type argument, the runtime generates code that uses the value types directly without boxing the value types.

Wenn ein Verweistyp als generisches Typargument verwendet wird, verwenden Sie die Handlesyntax.When using a reference type as a generic type argument, use the handle syntax. Wenn ein Werttyp als generisches Typargument verwendet wird, verwenden Sie den Namen des Typs direkt.When using a value type as a generic type argument, use the name of the type directly.

// generics_overview_2.cpp
// compile with: /clr
generic <typename T>

ref class GenericType {};
ref class ReferenceType {};

value struct ValueType {};

int main() {
    GenericType<ReferenceType^> x;
    GenericType<ValueType> y;
}

TypparameterType Parameters

Typparameter in einer generischen Klasse werden wie andere Bezeichner behandelt.Type parameters in a generic class are treated like other identifiers. Da der Typ nicht bekannt ist, gibt es jedoch Einschränkungen für deren Verwendung.However, because the type is not known, there are restrictions on their use. Sie können z.B. nicht Member und Methoden der Typparameterklasse verwenden, solange vom Typparameter nicht bekannt ist, dass er diese Member unterstützt.For example, you cannot use members and methods of the type parameter class unless the type parameter is known to support these members. Also müssen Sie für den Zugriff auf einen Member über den Typparameter den Typ, der den Member enthält, der Einschränkungenliste des Typparameters hinzufügen.That is, to access a member through the type parameter, you must add the type that contains the member to the type parameter's constraint list.

// generics_overview_3.cpp
// compile with: /clr
interface class I {
   void f1();
   void f2();
};

ref struct R : public I {
   virtual void f1() {}
   virtual void f2() {}
   virtual void f3() {}
};

generic <typename T>
where T : I
void f(T t) {
   t->f1();
   t->f2();
   safe_cast<R^>(t)->f3();
}

int main() {
   f(gcnew R());
}

Diese Einschränkungen gelten auch für Operatoren.These restrictions apply to operators as well. Ein uneingeschränkter generischer Typparameter kann nicht die Operatoren == und != zum Vergleichen von zwei Instanzen des Typparameters verwenden, falls der Typ diese Operatoren nicht unterstützt.An unconstrained generic type parameter may not use the == and != operators to compare two instances of the type parameter, in case the type does not support these operators. Diese Überprüfungen sind für Generics erforderlich, aber nicht für Vorlagen, da Generics zur Laufzeit mit einer beliebigen Klasse spezifiziert werden können, die die Einschränkungen erfüllt, wenn es zu spät ist, um zu überprüfen, ob ungültige Member verwendet werden.These checks are necessary for generics, but not for templates, because generics may be specialized at runtime with any class that satisfies the constraints, when it is too late to check for the use of invalid members.

Eine Standardinstanz des Typparameters kann mithilfe des ()-Operators erstellt werden.A default instance of the type parameter may be created by using the () operator. Beispiel:For example:

T t = T();

wobei T ein Typparameter in einer generischen Klasse oder Methodendefinition ist; die Variable wird mit ihrem Standardwert initialisiert.where T is a type parameter in a generic class or method definition, initializes the variable to its default value. Wenn T eine Verweisklasse ist, wird es ein NULL-Zeiger sein; wenn T eine Wertklasse ist, wird das Objekt mit 0 (null) initialisiert.If T is a ref class it will be a null pointer; if T is a value class, the object is initialized to zero. Dies wird als Standardinitialisierer bezeichnet.This is called a default initializer.

Weitere InformationenSee also

GenericsGenerics