- Dynamic Sidebar mit window.COURSES_MANIFEST für 13 Kurse (216 Kapitel) - Kurswechsler Dropdown mit Direktnavigation - Fortschrittsanzeige mit Solved-Checkmarks (✓) aus localStorage - Responsive Off-Canvas Drawer mit Floating Action Button (☰ Kapitel) & Backdrop auf Mobile/Tablets - Web-IDE Topbar Drawer-Button (☰ Kapitel) für unterbrechungsfreien Vollbild-Editor - Saubere Bereinigung redundanter statischer Legacy-Sidebars |
||
|---|---|---|
| .. | ||
| Aufgabe.cs | ||
| index.html | ||
| Musterloesung.cs | ||
| README.md | ||
| TestAufgabe.cs | ||
C# 09: Generics & Generic Constraints 🧬
Willkommen zu Modul 09 des C# Masterkurses! In diesem Kapitel lernst du, wie du flexible, hochgradig wiederverwendbare und typsichere Datenstrukturen in C# 12 entwickelst.
💡 1. Das Wichtigste in Kürze
Warum Generics?
Generics eliminieren die Notwendigkeit von Type-Casts und Boxing/Unboxing:
- Typsicherheit: Fehler werden bereits vom Roslyn-Compiler zur Build-Zeit erkannt.
- Performance: Wertetypen (wie
int,struct) landen direkt auf dem Stack bzw. in typspezifischen Arrays – keine teure Heap-Allokation. - Code-Wiederverwendung: Ein einzelner Algorithmus funktioniert für beliebig viele Typen.
Generic Constraints (where T : ...)
Mit Constraints sagst du dem Compiler, welche Fähigkeiten der Typ T mitbringen muss:
public class Repository<TEntity, TId>
where TEntity : class, IEntity<TId>, new()
where TId : notnull
{
// Hier können wir:
// - entity.Id aufrufen (durch IEntity<TId>)
// - TEntity instanziieren mit new TEntity() (durch new())
// - null zurückgeben (durch class)
}
Der Result<T> Typ (Functional Error Handling)
Statt Ausnahmen für reguläre Fehlerflüsse zu werfen, kapselt Result<T> Erfolg oder Misserfolg:
var result = Result<Customer>.Success(new Customer { Name = "Alice" });
if (result.IsSuccess)
{
Console.WriteLine($"Kunde geladen: {result.Value.Name}");
}
🎯 Teilziele in Aufgabe.cs
-
TODO 1:
IEntity<TId>Interface
Definiere ein generisches Entity-Interface mitTId Id { get; set; }. -
TODO 2:
Result<T>Wrapper-Klasse
Implementiere einen unmodifizierbaren Result-Container mitIsSuccess,Value,Errorsowie statischen Factory-MethodenSuccess(T)undFailure(string). -
TODO 3:
InMemoryRepository<TEntity, TId>
Erstelle ein In-Memory Repository mit den Constraintswhere TEntity : class, IEntity<TId>, new()undwhere TId : notnull. ImplementiereAdd,GetById,GetAll,Remove,CountundCreateDefault(). -
TODO 4: Generische Hilfsmethoden
ImplementiereSwap<T>(ref T a, ref T b)undFindMatches<T>(IEnumerable<T> items, Predicate<T> filter).