Generika zur Laufzeit (C#-Programmierhandbuch)Generics in the Run Time (C# Programming Guide)

Beim Kompilieren eines generischen Typs oder einer generischen Methode in Microsoft Intermediate Language (MSIL) wird über Metadaten auf das Vorkommen von Typparametern hingewiesen.When a generic type or method is compiled into Microsoft intermediate language (MSIL), it contains metadata that identifies it as having type parameters. Die Art der Verwendung von MSIL für einen generischen Typ hängt davon ab, ob es sich bei dem übergebenen Typparameter um einen Werttyp oder einen Referenztyp handelt.How the MSIL for a generic type is used differs based on whether the supplied type parameter is a value type or reference type.

Wenn das erste Mal ein generischer Typ mit einem Werttyp als Parameter erstellt wird, erstellt die Laufzeit einen spezialisierten generischen Typ, bei dem übergebene Parameter an den entsprechenden Stellen in MSIL ersetzt werden.When a generic type is first constructed with a value type as a parameter, the runtime creates a specialized generic type with the supplied parameter or parameters substituted in the appropriate locations in the MSIL. Spezialisierte generische Typen werden für jeden eindeutigen Werttyp, der als Parameter verwendet wird, einmal erstellt.Specialized generic types are created one time for each unique value type that is used as a parameter.

Angenommen, im Programmcode wurde ein Stapel deklariert, der aus ganzen Zahlen erstellt wurde:For example, suppose your program code declared a stack that is constructed of integers:

Stack<int> stack;

An diesem Punkt generiert die Laufzeit eine spezialisierte Version der Klasse Stack<T>, in der der Parameter durch die entsprechende ganze Zahl ersetzt wird.At this point, the runtime generates a specialized version of the Stack<T> class that has the integer substituted appropriately for its parameter. Bei Verwendung eines Stapels aus ganzen Zahlen wird jetzt immer die generierte spezialisierte Klasse Stack<T> verwendet.Now, whenever your program code uses a stack of integers, the runtime reuses the generated specialized Stack<T> class. Im folgenden Beispiel werden zwei Instanzen eines Stapels aus ganzen Zahlen erstellt, die eine Instanz des Stack<int>-Codes gemeinsam nutzen:In the following example, two instances of a stack of integers are created, and they share a single instance of the Stack<int> code:

Stack<int> stackOne = new Stack<int>();
Stack<int> stackTwo = new Stack<int>();

Angenommen, dass an anderer Stelle im Code jedoch eine weitere Stack<T>-Klasse erstellt wird, mit einem anderen Werttyp, z.B. long, oder einer benutzerdefinierten Struktur als Parameter.However, suppose that another Stack<T> class with a different value type such as a long or a user-defined structure as its parameter is created at another point in your code. Daraufhin generiert die Laufzeit eine andere Version des generischen Typs und ersetzt long an den entsprechenden Stellen in MSIL.As a result, the runtime generates another version of the generic type and substitutes a long in the appropriate locations in MSIL. Konvertierungen sind nicht mehr notwendig, da jede spezialisierte generische Klasse den Werttyp nativ enthält.Conversions are no longer necessary because each specialized generic class natively contains the value type.

Bei Referenztypen unterscheidet sich die Funktionsweise von Generika geringfügig.Generics work somewhat differently for reference types. Wenn das erste Mal ein generischer Typ mit einem beliebigem Referenztyp erstellt wird, erstellt die Laufzeit einen spezialisierten generischen Typ, bei dem die Parameter durch Objektverweise in MSIL ersetzt werden.The first time a generic type is constructed with any reference type, the runtime creates a specialized generic type with object references substituted for the parameters in the MSIL. Wenn jetzt ein konstruierter Typ mit einem Referenztyp als Parameter instanziiert wird (unabhängig davon, um welchen Typ es sich dabei handelt), wird die zuvor erstellte spezialisierte Version des generischen Typs verwendet.Then, every time that a constructed type is instantiated with a reference type as its parameter, regardless of what type it is, the runtime reuses the previously created specialized version of the generic type. Dies ist möglich, da alle Verweise die gleiche Größe haben.This is possible because all references are the same size.

Angenommen, Sie verfügen über zwei Referenztypen, eine Customer-Klasse und eine Order-Klasse, und Sie haben einen Stapel von Customer-Typen erstellt:For example, suppose you had two reference types, a Customer class and an Order class, and also suppose that you created a stack of Customer types:

class Customer { }
class Order { }
Stack<Customer> customers;

An dieser Stelle generiert die Laufzeit eine spezialisierte Version der Klasse Stack<T>, die anstelle von Daten Objektverweise speichert, die zu einem späteren Zeitpunkt mit Daten gefüllt werden.At this point, the runtime generates a specialized version of the Stack<T> class that stores object references that will be filled in later instead of storing data. Angenommen, die nächste Codezeile erstellt einen Stapel eines anderen Referenztyps mit dem Namen Order:Suppose the next line of code creates a stack of another reference type, which is named Order:

Stack<Order> orders = new Stack<Order>();

Anders als bei Werttypen wird für den Typ Stack<T> keine weitere spezialisierte Version der Klasse Order erstellt.Unlike with value types, another specialized version of the Stack<T> class is not created for the Order type. Stattdessen wird eine Instanz der spezialisierten Version der Klasse Stack<T> erstellt und die Variable orders so festgelegt, dass sie darauf verweist.Instead, an instance of the specialized version of the Stack<T> class is created and the orders variable is set to reference it. Angenommen, Sie würden dann auf eine Codezeile stoßen, die einen Stapel des Typs Customer erstellt:Suppose that you then encountered a line of code to create a stack of a Customer type:

customers = new Stack<Customer>();

Wie auch bei der vorherigen Verwendung der mit dem Typ Order erstellten Klasse Stack<T> wird eine weitere Instanz der spezialisierten Klasse Stack<T> erstellt.As with the previous use of the Stack<T> class created by using the Order type, another instance of the specialized Stack<T> class is created. Die darin enthaltenen Zeiger werden so festgelegt, dass sie auf einen Arbeitsspeicherbereich von der Größe eines Customer-Typs verweisen.The pointers that are contained therein are set to reference an area of memory the size of a Customer type. Da die Anzahl der Referenztypen von Programm zu Programm sehr unterschiedlich sein kann, wird bei der C#-Implementierung von Generika eine übermäßige Zunahme des Codeumfangs dadurch verhindert, dass die Anzahl der spezialisierten Klassen, die vom Compiler für generische Klassen von Referenztypen erstellt werden, auf eine reduziert wird.Because the number of reference types can vary wildly from program to program, the C# implementation of generics greatly reduces the amount of code by reducing to one the number of specialized classes created by the compiler for generic classes of reference types.

Weiterhin gilt, dass eine mit einem Werttyp- oder Referenztypparameter instanziierte generische C#-Klasse zur Laufzeit mittels Reflektion abgefragt werden kann. Dabei können sowohl der tatsächliche Typ als auch der Typparameter ermittelt werden.Moreover, when a generic C# class is instantiated by using a value type or reference type parameter, reflection can query it at runtime and both its actual type and its type parameter can be ascertained.

Siehe auchSee Also

System.Collections.Generic
C#-ProgrammierhandbuchC# Programming Guide
Einführung in GenerikaIntroduction to Generics
GenerikaGenerics