Generics
Generics in C# sind ein zentrales Konzept, das es Entwicklern ermöglicht, Klassen, Methoden und Datenstrukturen zu definieren, die mit beliebigen Datentypen arbeiten können, ohne die Typensicherheit zur Laufzeit zu gefährden. Durch den Einsatz von Generics können wiederverwendbare Komponenten erstellt werden, die Code-Duplikation vermeiden und gleichzeitig die Wartbarkeit und Skalierbarkeit von Softwareprojekten erhöhen.
Generics sind besonders nützlich bei der Implementierung von Collections wie List
In diesem Tutorial lernen die Leser, wie man generische Klassen und Methoden definiert, Typbeschränkungen anwendet und Generics in praktischen Projekten einsetzt. Ziel ist es, wiederverwendbare, sichere und performante Komponenten zu entwickeln und zu verstehen, wie Generics die Softwarearchitektur in C#-Projekten positiv beeinflussen.
Grundlegendes Beispiel
textusing System;
namespace GenericsDemo
{
// Definition einer generischen Klasse
public class Box<T>
{
private T content;
public void Add(T item)
{
content = item;
}
public T Get()
{
return content;
}
}
class Program
{
static void Main(string[] args)
{
// Generische Klasse mit int
Box<int> intBox = new Box<int>();
intBox.Add(42);
Console.WriteLine("Inhalt der Box: " + intBox.Get());
// Generische Klasse mit string
Box<string> stringBox = new Box<string>();
stringBox.Add("Hallo Welt");
Console.WriteLine("Inhalt der Box: " + stringBox.Get());
}
}
}
Dieses Beispiel demonstriert die grundlegende Nutzung von Generics in C#. Die Klasse Boxcontent
speichert den Wert, während die Methoden Add
und Get
das Setzen und Abrufen des Inhalts ermöglichen.
Im Main-Programm werden Box
Praktisch eignet sich dieses Muster für wiederverwendbare Container, Caching-Systeme oder Bibliotheken für Algorithmen in C#-Projekten. Es bildet die Grundlage für komplexere Anwendungen und modulare Architekturen.
Praktisches Beispiel
textusing System;
using System.Collections.Generic;
namespace AdvancedGenericsDemo
{
// Generische Repository-Klasse mit Typbeschränkung
public class Repository<T> where T : class
{
private List<T> items = new List<T>();
public void Add(T item)
{
if (item == null)
throw new ArgumentNullException(nameof(item), "Item darf nicht null sein");
items.Add(item);
}
public T Find(Predicate<T> predicate)
{
return items.Find(predicate);
}
public void DisplayAll()
{
foreach (var item in items)
{
Console.WriteLine(item.ToString());
}
}
}
class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public override string ToString()
{
return $"{Name} - {Price} €";
}
}
class Program
{
static void Main(string[] args)
{
Repository<Product> productRepo = new Repository<Product>();
productRepo.Add(new Product { Name = "Laptop", Price = 1500 });
productRepo.Add(new Product { Name = "Smartphone", Price = 800 });
Console.WriteLine("Alle Produkte:");
productRepo.DisplayAll();
Product expensiveProduct = productRepo.Find(p => p.Price > 1000);
Console.WriteLine("Teuerstes Produkt: " + expensiveProduct);
}
}
}
In diesem praktischen Beispiel verwaltet die generische Repository-Klasse Repositorywhere T : class
, die nur Referenztypen zulässt. Die Methoden Add
, Find
und DisplayAll
ermöglichen eine sichere und effiziente Verwaltung der Elemente. Das Hinzufügen von Nullprüfungen stellt die Robustheit der Anwendung sicher.
Die Klasse Product stellt ein reales Objekt mit Name und Price dar und überschreibt ToString für eine einfache Ausgabe. Im Main-Programm wird gezeigt, wie Repository
Best Practices und häufige Fehler bei Generics in C#:
- Typbeschränkungen verwenden, um gültige Typen zu gewährleisten.
- Keine nicht verwalteten Ressourcen ohne ordnungsgemäße Freigabe in generischen Containern speichern, um Speicherlecks zu vermeiden.
- Eingebaute generische Collections (List
, Dictionary\ ) für optimale Performance nutzen. - Exceptions klar behandeln, z.B. bei null oder ungültigen Eingaben.
- Generics nicht unnötig verallgemeinern, da dies die Wartbarkeit erschwert.
- Beim Debugging auf tatsächliche Typen achten.
- Performance durch Minimierung von Boxing/Unboxing optimieren.
- Sicherheit: Eingabetypen validieren und sensible Daten in generischen Interfaces schützen.
📊 Referenztabelle
C# Element/Concept | Description | Usage Example |
---|---|---|
Generische Klasse | Klasse, die mehrere Typen handhaben kann | public class Box<T> { T content; } |
Generische Methode | Methode für verschiedene Typen | public T GetItem<T>(T item) { return item; } |
Constraints | Beschränkt zulässige Typen | where T : class, new() |
List<T> | Generische Listen-Collection | List<int> numbers = new List<int>(); |
Dictionary\<TKey,TValue> | Generische Key-Value-Collection | Dictionary\<string,int> ages = new Dictionary\<string,int>(); |
Predicate<T> | Delegate für bedingte Suche | items.Find(p => p.Price > 100); |
Zusammenfassung und nächste Schritte:
Generics in C# ermöglichen es, effizienten, wiederverwendbaren und typensicheren Code zu schreiben. Mit generischen Klassen, Methoden, Collections und Constraints lassen sich komplexe Datenverarbeitungen und Algorithmen implementieren, während Redundanz reduziert wird. Generics fördern modulare und wartbare Architekturen, verringern Laufzeitfehler und optimieren die Gesamtperformance.
Weitere Schritte umfassen das Erlernen fortgeschrittener Collections wie Stack
🧠 Testen Sie Ihr Wissen
Testen Sie Ihr Wissen
Testen Sie Ihr Verständnis dieses Themas mit praktischen Fragen.
📝 Anweisungen
- Lesen Sie jede Frage sorgfältig
- Wählen Sie die beste Antwort für jede Frage
- Sie können das Quiz so oft wiederholen, wie Sie möchten
- Ihr Fortschritt wird oben angezeigt