English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Generische Typen beziehen sich auf allgemeine Formen und nicht auf spezifische Formen. In C# bedeutet Generische nicht spezifisch für einen bestimmten Datentyp.
C# ermöglicht es Ihnen, generische Klassen, Schnittstellen, abstrakte Klassen, Felder, Methoden, statische Methoden, Eigenschaften, Ereignisse, Delegaten und Operatoren ohne spezifische Datentypen zu definieren. Typparameter sind Platzhalter für spezifische Typen, die beim Erstellen von Instanzen generischer Typen angegeben werden.
Generische Typen werden durch die Angabe von Typparametern in eckigen Klammern nach dem Typnamen deklariert, z.B. TypeName<T>, hier ist T der Typparameter.
Generische Klassen werden durch die Verwendung von Typparametern in eckigen Klammern nach dem Klassennamen definiert. Unten ist eine generische Klasse definiert.
class DataStore<T> { public T Data { get; set; } }
Oben ist DataStore eine generische Klasse. T wird als Typparameter bezeichnet und kann als Feld, Eigenschaft, Methodenparameter, Rückgabetyp und Typ des Delegaten in der Klasse DataStore verwendet werden. Zum Beispiel ist Data ein generisches Eigenschaft, da wir den Typparameter T als Typ verwendet haben, anstatt eines bestimmten Datentyps.
Sie können auch mehrere Typparameter definieren und durch Kommas trennen.
class KeyValuePair<TKey, TValue> { public TKey Key { get; set; } public TValue Value { get; set; } }
Sie können Instanzen generischer Klassen erstellen, indem Sie die tatsächlichen Typen in Klammern angeben. Below wird eine Instanz der generischen Klasse DataStore erstellt.
DataStore<string> store = new DataStore<string>();
Oben haben wir string in Klammern angegeben, wenn wir die Instanz erstellt haben. Daher wird T bei der Kompilierung durch jeden Typ T ersetzt, der im gesamten Klassenbereich verwendet wird. Daher ist der Typ des Data-Attributs string.
Das folgende Diagramm erläutert die Funktionsweise der Generics.
Sie können einem Data-Attribut einen String-Wert zuweisen. Der Versuch, einen anderen Wert als String zuzuweisen, führt zu einem Kompilierungsfehler.
DataStore<string> store = new DataStore<string>(); store.Data = "Hello World!";//obj.Data = 123; //Kompilierungsfehler
Sie können unterschiedliche Datentypen für verschiedene Objekte angeben, wie folgt.
DataStore<string> strStore = new DataStore<string>(); strStore.Data = "Hello World!"; //strStore.Data = 123; // Kompilierungsfehler DataStore<int> intStore = new DataStore<int>(); intStore.Data = 100; //intStore.Data = "Hello World!"; // Kompilierungsfehler KeyValuePair<int, string> kvp1 = new KeyValuePair<int, string>(); kvp1.Key = 100; kvp1.Value = "Hundred"; KeyValuePair<string, string> kvp2 = new KeyValuePair<string, string>(); kvp2.Key = "IT"; kvp2.Value = "Information Technology";
Generische Klassen erhöhen die Wiederverwendbarkeit. Je mehr Typen, desto höher die Wiederverwendbarkeit. Allerdings kann eine übermäßige Generalisierung den Code schwerfällig und schwer zu warten machen.
Generische Klassen können Basisklassen für andere generische oder nicht generische Klassen oder abstrakte Klassen sein.
Generische Klassen können von anderen generischen oder nicht generischen Interfaces, Klassen oder abstrakten Klassen abgeleitet werden.
Generische Klassen können generische Felder enthalten, aber diese können nicht initialisiert werden.
class DataStore<T> { public T data; }
Below wird ein generischer Array deklariert.
class DataStore<T> { public T[] data = new T[10]; }
Methoden, die Typenparameter zur Angabe ihres Rückgabetyps oder ihrer Parameter verwenden, werden generische Methoden genannt.
class DataStore<T> { private T[] _data = new T[10]; public void AddOrUpdate(int index, T item) { if(index >= 0 && index < 10) _data[index] = item; } public T GetData(int index) { if(index >= 0 && index < 10) return _data[index]; else return default(T); } }
Die Methoden AddorUpdate() und GetData() sind generische Methoden. Der tatsächliche Datentyp des Parameters item wird bei der Instanziierung der Klasse DataStore<T> angegeben, wie folgt.
DataStore<string> cities = new DataStore<string>(); cities.AddOrUpdate(0, "Mumbai"); cities.AddOrUpdate(1, "Chicago"); cities.AddOrUpdate(2, "London"); DataStore<int> empIds = new DataStore<int>(); empIds.AddOrUpdate(0, 50); empIds.AddOrUpdate(1, 65); empIds.AddOrUpdate(2, 89);
Generische Parameter können mit mehreren Parametern zusammen verwendet werden, die entweder generische oder nicht generische Parameter und Rückgabetypen haben. Hier sind gültige Überschreibungen generischer Methoden.
public void AddOrUpdate(int index, T data) { } public void AddOrUpdate(T data1, T data2) { } public void AddOrUpdate<U>(T data1, U data2) { } public void AddOrUpdate(T data) { }
Durch die Angabe des Typenparameters in Klammern mit dem Methodennamen können nicht generische Klassen generische Methoden enthalten, wie folgt gezeigt.
class Printer { public void Print<T>(T data) { Console.WriteLine(data); } } Printer printer = new Printer(); printer.Print<int>(100); printer.Print(200); // Nach dem angegebenen Wert schließen printer.Print<string>("Hello"); printer.Print("World!"); // Nach dem angegebenen Wert schließen
Generische erhöhen die Wiederverwendbarkeit des Codes. Es ist nicht erforderlich, Code zu schreiben, um verschiedene Datentypen zu verarbeiten.
Generische sind typsicher. Wenn versucht wird, einen anderen Datentyp als den in der Definition angegebenen zu verwenden, wird eine Kompilierungszeitfehler aufgetreten.
Generische haben einen Performance-Vorteil, weil sie die Möglichkeit der Boxung und Unboxing eliminieren.