Generics (Klassen & Methoden)
Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy. Lektion 42 von 70.
Generics ermöglichen es dir, Klassen und Methoden zu schreiben, die mit jedem Datentyp funktionieren und dabei die Typsicherheit gewährleisten. Statt separate Klassen für IntList, StringList und DoubleList zu schreiben, schreibst du eine generische Klasse, die sie alle verarbeitet.
Eine generische Klasse verwendet einen Typparameter, der üblicherweise T heißt und in spitze Klammern eingeschlossen ist:
public class Box<T>
{
private T content;
public void Store(T item) => content = item;
public T Retrieve() => content;
}
// Verwendung mit verschiedenen Typen
Box<int> intBox = new Box<int>();
intBox.Store(42);
Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");Wenn du Box<int> erstellst, ersetzt der Compiler jedes T durch int. Dadurch wird die Typprüfung zur Kompilierzeit ermöglicht – du kannst nicht versehentlich eine Zeichenfolge in einer int-Box speichern.
Generische Methoden funktionieren ähnlich und ermöglichen es einer einzelnen Methode, mit verschiedenen Typen zu arbeiten:
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y); // x=2, y=1Der Compiler leitet den Typ aus den Argumenten ab, du musst also Swap<int> nicht ausdrücklich schreiben. Generics bilden die Grundlage für Sammlungen wie List<T> und Dictionary<TKey, TValue> und ermöglichen wiederverwendbaren, typsicheren Code.
Aufgabe
EinfachErstellen wir ein generisches Storage<T>-System, das Elemente beliebigen Typs aufnehmen und verwalten kann. Du erstellst eine wiederverwendbare Containerklasse, die die Leistungsfähigkeit von Generics demonstriert – einmal schreiben und mit Ganzzahlen, Zeichenfolgen oder jedem anderen Typ verwenden!
Du organisierst deinen Code auf zwei Dateien:
Storage.cs: Erstelle eine generische KlasseStorage<T>im NamespaceDataStorage. Dein Speichercontainer sollte:- Ein privates Array vom Typ
Tzum Speichern der Elemente und eineCount-Eigenschaft haben, die nachverfolgt, wie viele Elemente gespeichert sind - Im Konstruktor eine Kapazität entgegennehmen, um das interne Array zu initialisieren
- Eine
Add(T item)-Methode haben, die ein Element hinzufügt, wenn Platz vorhanden ist - Eine
Get(int index)-Methode haben, die das Element am angegebenen Index zurückgibt - Eine
GetAll()-Methode haben, die alle gespeicherten Elemente, verbunden durch", ", zurückgibt
- Ein privates Array vom Typ
Program.cs: Zeige in deiner Hauptdatei, wie deine generische Klasse mit zwei verschiedenen Typen funktioniert. Erstelle einStorage<int>und einStorage<string>, füge jedem Elemente hinzu und zeige, dass dieselbe Klasse nahtlos mit beiden Typen funktioniert.
Du erhältst vier Eingaben:
- Erste zu speichernde Ganzzahl
- Zweite zu speichernde Ganzzahl
- Erste zu speichernde Zeichenfolge
- Zweite zu speichernde Zeichenfolge
Erstelle einen Ganzzahl-Speicher mit einer Kapazität von 5 und einen Zeichenfolgen-Speicher mit einer Kapazität von 5. Füge die beiden Ganzzahlen zum Ganzzahl-Speicher und die beiden Zeichenfolgen zum Zeichenfolgen-Speicher hinzu.
Gib die Ausgabe in diesem Format aus:
Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}Wenn die Eingaben beispielsweise 42, 100, Hello und World sind, sollte die Ausgabe wie folgt aussehen:
Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: HelloBeachte, dass du die Klasse Storage<T> einmal schreibst, sie aber sowohl mit int als auch mit string einwandfrei funktioniert – das ist die Magie von Generics! Der Compiler gewährleistet die Typsicherheit, sodass du nicht versehentlich eine Zeichenfolge zu deinem Ganzzahl-Speicher hinzufügen kannst.
Probier es selbst
using System;
using DataStorage;
class Program
{
public static void Main(string[] args)
{
// Eingaben einlesen
int num1 = Convert.ToInt32(Console.ReadLine());
int num2 = Convert.ToInt32(Console.ReadLine());
string str1 = Console.ReadLine();
string str2 = Console.ReadLine();
// TODO: Einen Storage<int> mit Kapazität 5 erstellen
// TODO: Die beiden Ganzzahlen zum Ganzzahlspeicher hinzufügen
// TODO: Einen Storage<string> mit Kapazität 5 erstellen
// TODO: Die beiden Zeichenfolgen zum Zeichenfolgenspeicher hinzufügen
// TODO: Die Ausgabe im erforderlichen Format ausgeben
// Int storage: {GetAll()}
// Int-Anzahl: {Count}
// Erster int: {Get(0)}
// String storage: {GetAll()}
// String count: {Count}
// First string: {Get(0)}
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienNamespaces & DirektivenEinführung in Klassen & ObjekteDas 'this'-SchlüsselwortMethoden und ParameterFelder vs. EigenschaftenKonstruktorenObjektinitialisiererWiederholung – Einfacher Taschenrechner4Vererbung
Grundlegende Vererbungs-(:)-SyntaxDas „base“-Schlüsselwort„virtual“- und „override“-SchlüsselwörterVersiegelte KlassenDie „object“-BasisklasseWiederholung – Mitarbeiterhierarchie7Erweiterte Funktionen
Überladen von OperatorenIndexer (this[])ToString()-ÜberschreibungErweiterungsmethodenRückblick – Benutzerdefinierte Liste10Entwurfsmuster Teil 1
Einführung in EntwurfsmusterThread-sicheres SingletonFactory-MusterObserver-Muster (Events)Strategy-Muster13Abschließende Herausforderungen
E-Learning-PlattformKomponente für SpielfigurenFahrzeugvermietungsdienst2Eigenschaften & statische Member
Automatisch implementierte EigenschaftenNur lesbare/schreibbare EigenschaftenStatische Felder & MethodenStatische KlassenMember mit Ausdruckskörpern5Polymorphie & Interfaces
Compile- vs. Laufzeit-PolymorphieInterface vs. abstrakte KlasseMehrere InterfacesExplizite InterfacesUpcasting & DowncastingWiederholung – Formenrechner8Fortgeschrittene OOP-Konzepte
Komposition statt VererbungGenerics (Klassen & Methoden)Delegates und EventsAttribute und ReflectionIDisposable & using-AnweisungGrundlagen der Dependency Injection3Klassenarchitektur
Instanz- vs. statische DatenSchlüsselwörter 'readonly' & 'const'Backing FieldsRückblick – Bankkontenverwaltung6Kapselung
ZugriffsmodifikatorenEigenschaften zur KapselungImplementierung der DatenkapselungMuster für UnveränderlichkeitRückblick – SchülerdatenÜbe selbstständig: Online-C#-Compiler