Vorteile von Generika (C#-Programmierhandbuch)

Aktualisiert: November 2007

Generika bieten die Lösung für eine Einschränkung in früheren Versionen der Common Language Runtime (CLR) und von C#: Durch Umwandlung von Typen in den bzw. aus dem universellen Basistyp Object wird Verallgemeinerung erreicht. Indem Sie eine generische Klasse erstellen, können Sie eine Auflistung erstellen, die zur Kompilierzeit typsicher ist.

Die Grenzen der Verwendung nicht generischer Auflistungsklassen werden durch ein kurzes Programm verdeutlicht, in dem die ArrayList-Auflistungsklasse aus der .NET Framework-Klassenbibliothek verwendet wird. ArrayList ist eine äußerst praktische Auflistungsklasse, die unverändert verwendet werden kann, um beliebige Verweis- und Werttypen zu speichern.

// The .NET Framework 1.1 way to create a list:
System.Collections.ArrayList list1 = new System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);

System.Collections.ArrayList list2 = new System.Collections.ArrayList();
list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");

Aber dieser Komfort hat seinen Preis. Jeder Verweis- oder Werttyp, der ArrayList hinzugefügt wird, wird implizit in Object umgewandelt. Wenn es sich bei den Elementen um Werttypen handelt, müssen sie vor dem Hinzufügen zur Liste durch Boxing und beim Abrufen durch Unboxing umgewandelt werden. Sowohl die Umwandlung als auch die Boxing- und Unboxingoperationen vermindern die Leistung. Die Auswirkung von Boxing und Unboxing kann sich besonders bemerkbar machen, wenn umfassende Auflistungen durchlaufen werden müssen.

Bei der anderen Einschränkung handelt es sich um das Fehlen einer Typüberprüfung zur Kompilierzeit. Da ArrayList alles in Object umwandelt, gibt es zur Kompilierzeit keine Möglichkeit zu verhindern, dass Clientcode Folgendes verursacht:

System.Collections.ArrayList list = new System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may cause an error later.
list.Add("It is raining in Redmond.");

int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
    t += x;
}

Durchaus zulässig und manchmal beim Erstellen heterogener Auflistungen vielleicht sogar beabsichtigt, scheint das Kombinieren von Zeichenfolgen und ints in einer gemeinsamen ArrayList doch eher ein Programmierfehler zu sein, der erst zur Laufzeit entdeckt werden kann.

In den Versionen 1.0 und 1.1 der Programmiersprache C# konnten solche Gefahren durch verallgemeinerten Code in den Auflistungsklassen der .NET Framework-Basisklassenbibliothek nur durch selbstgeschriebene typspezifische Auflistungen vermieden werden. Da eine solche Klasse immer nur für einen Datentyp verwendbar ist, geht der Nutzen der Verallgemeinerung natürlich verloren, sodass Sie die Klasse für jeden Typ, der gespeichert wird, neu schreiben müssen.

Deshalb wird für ArrayList und ähnliche Klassen unbedingt eine Möglichkeit benötigt, im Clientcode den jeweils zu verwendenden Datentyp für jede Instanz einzeln anzugeben. Dadurch würde die Umwandlung in T:System.Object überflüssig, und der Compiler könnte eine Typüberprüfung durchführen. Mit anderen Worten: Für ArrayList ist ein Typparameter erforderlich. Genau dies wird durch Generika bereitgestellt. In der generischen List<T>-Auflistung im N:System.Collections.Generic-Namespace sieht die gleiche Operation (Hinzufügen von Elementen zur Auflistung) folgendermaßen aus:

// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();

// No boxing, no casting:
list1.Add(3);

// Compile-time error:
// list1.Add("It is raining in Redmond.");

Bei Clientcode bildet das Typargument in der Deklaration und der Instanziierung die einzige Syntaxergänzung, die bei List<T> gegenüber ArrayList vorgenommen wird. Im Gegenzug für diese geringfügig komplexere Codierung können Sie nun eine Liste erstellen, die nicht nur sicherer ist als ArrayList, sondern auch erheblich schneller, und zwar besonders dann, wenn es sich bei den Elementen um Werttypen handelt.

Siehe auch

Konzepte

C#-Programmierhandbuch

Referenz

Einführung in Generika (C#-Programmierhandbuch)

System.Collections.Generic

Boxing und Unboxing (C#-Programmierhandbuch)

Weitere Ressourcen

Auflistungen Best Practices