Generics und Typisierung in C#: Flexiblen Code ohne Copy-Paste schreiben

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Generics und Typisierung in C#: Warum kommt man ohne sie nicht aus?



Stellen Sie sich vor, Sie bauen ein Haus, aber jedes Mal, wenn Sie einen Nagel einschlagen müssen, schnitzen Sie einen neuen Hammer speziell für diesen Nagel. Absurd? Genauso sieht Code ohne Verallgemeinerungen (Generics) aus. In C# sind Generics dieser universelle Hammer, der für jede Aufgabe geeignet ist, ohne dabei an Präzision zu verlieren.



Heute werden wir analysieren, wie Generics und Typisierung in C# Ihren Code von einem Haufen zusammenhangloser Krücken in ein schlankes, flexibles und sicheres System verwandeln. Sie erfahren, wie Sie universelle Methoden und Klassen schreiben, die mit beliebigen Datentypen arbeiten, ohne dabei Leistungseinbußen in Kauf zu nehmen. Los geht's!



Was sind Generics und wozu braucht man sie?



Generics (Verallgemeinerungen) sind ein Mechanismus, der es ermöglicht, Klassen, Methoden und Schnittstellen zu erstellen, die mit jedem Datentyp arbeiten, dabei aber die strenge Typisierung zur Kompilierzeit beibehalten. Klingt kompliziert? In der Praxis ist es einfach.



Vor der Einführung von Generics in C# (Version 2.0, 2005) verwendeten Entwickler zwei Ansätze:

  • Copy-Paste — Erstellung einer separaten Klasse für jeden Typ (int, string, double usw.).
  • object — Verwendung des Basistyps object, was zu Boxing/Unboxing und Leistungseinbußen führte.


Beide Varianten sind schlecht. Die erste kostet Zeit, die zweite kostet Leistung. Generics lösen beide Probleme auf einmal.



Wie sehen Generics in der Praxis aus?



// Ohne Generics: Copy-Paste für jeden Typpublic class IntList{    private int[] items = new int[10];    public void Add(int item) { /* ... */ }}

public class StringList{ private string[] items = new string[10]; public void Add(string item) { /* ... */ }}

// Mit Generics: Eine Klasse für alle Fällepublic class GenericList<T>{ private T[] items = new T[10]; public void Add(T item) { /* ... */ }}

// Verwendungvar intList = new GenericList<int>();var stringList = new GenericList<string>();


Beachten Sie: GenericList<T> ist eine Vorlage. Anstelle von T setzen Sie einen beliebigen Typ ein (int, string, Ihre eigene Klasse), und der Compiler erstellt eine konkrete Version des Codes für diesen Typ. Keine Duplizierung, kein object.



Typisierung in C#: statisch, streng, sicher



Bevor wir tiefer eintauchen, erinnern wir uns daran, dass C# eine Sprache mit statischer Typisierung ist. Das bedeutet, dass der Typ jeder Variable zur Kompilierzeit bestimmt wird. Generics verletzen diese Regel nicht, sondern verstärken sie sogar.



Wenn Sie List<int> schreiben, weiß der Compiler genau, dass sich in der Liste nur ganze Zahlen befinden. Versuchen Sie, einen String hinzuzufügen, erhalten Sie einen Kompilierfehler und keine Laufzeitausnahme. Das ist Typsicherheit.



Generics vs object: Der Leistungskampf



// Schlechtes Beispiel mit objectArrayList badList = new ArrayList();badList.Add(123);           // Boxing int -> objectint value = (int)badList[0]; // Unboxing object -> int

// Gutes Beispiel mit GenericsList<int> goodList = new List<int>();goodList.Add(123); // Ohne Boxingint value = goodList[0]; // Ohne Unboxing


Bei Werttypen (int, double, struct) kann der Leistungsunterschied das 10- bis 20-fache betragen. Bei Referenztypen (class) gibt es kein Boxing, aber Generics gewinnen trotzdem durch das Fehlen von Typkonvertierungen.



Generische Methoden: Flexibilität ohne überflüssigen Code



Generics funktionieren nicht nur mit Klassen, sondern auch mit Methoden. Angenommen, Sie müssen eine Methode schreiben, die zwei Elemente vertauscht. Ohne Generics müssten Sie eine Reihe von Überladungen schreiben:



// Ohne Genericspublic void SwapInt(ref int a, ref int b) { int temp = a; a = b; b = temp; }public void SwapString(ref string a, ref string b) { string temp                

Blogs

Buchempfehlungen