⚡ Lehrpfad 3: LINQ, Generics & Async/Await

C# 12: Exception Handling & Deterministic Resource Cleanup

Schreibe ausfallsichere Enterprise-Anwendungen: Eigene Domain-Exceptions, Exception Filters (when), das IDisposable-Muster und automatisches Ressourcen-Cleanup mit using var.

📂 Dateien dieser Lerneinheit:
📄 Aufgabe.cs (Startercode) 🧪 TestAufgabe.cs (xUnit Tests) 💡 Musterloesung.cs (Lösung) 📖 README.md

🛡️ 1. Domain Exceptions & Exception Filtering mit when

In Enterprise-Anwendungen wirft man keine generischen Exception-Objekte, sondern präzise typisierte Custom Domain Exceptions, die wichtige Fachdaten (z.B. Konto-ID, geforderter Betrag, Fehlercode) transportieren.

Mit C# Exception Filters (catch (...) when (Bedingung)) kannst du Ausnahmen basierend auf ihren Eigenschaften gezielt abfangen, ohne den Aufrufstapel (Stack Trace) zu zerstören:

try
{
    bankService.TransferFunds(sourceAccountId, targetAccountId, 50000m);
}
catch (InsufficientFundsException ex) when (ex.RequestedAmount > 10000m)
{
    // Spezieller Handler für Großbetrags-Fehlschläge (z.B. Security-Alert auslösen)
    logger.LogCritical($"Großüberweisung von {ex.RequestedAmount}€ fehlgeschlagen! Saldo: {ex.CurrentBalance}€");
}
catch (BankDomainException ex)
{
    // Allgemeiner Handler für sonstige Bank-Fehler
    logger.LogWarning($"Bankfehler {ex.ErrorCode}: {ex.Message}");
}

🧹 2. Das IDisposable Muster & Modernes using var

Der .NET Garbage Collector bereinigt ausschließlich verwalteten Speicher (Heap). Unmanaged Ressourcen wie Dateihandles, Datenbankverbindungen oder Netzwerk-Sockets müssen deterministisch freigegeben werden.

{ // Scope-Beginn
  using var scope = new AuditLogScope("Transfer-102"); // Ressource reservieren
  scope.WriteEntry("Operation läuft...");
} // Scope-Ende ──► Compiler ruft scope.Dispose() automatisch auf (auch bei Exceptions!)
public sealed class AuditLogScope : IDisposable
{
    private bool _disposed;
    public string OperationName { get; }

    public AuditLogScope(string opName)
    {
        OperationName = opName;
        Console.WriteLine($"[AUDIT-START] {OperationName}");
    }

    public void Dispose()
    {
        if (!_disposed)
        {
            Console.WriteLine($"[AUDIT-END] {OperationName} abgeschlossen.");
            _disposed = true;
        }
    }
}
🏢 Didaktische Analogie: Das Hotel-Zimmerkarten-System

Beim Betreten des Raums aktivierst du mit der Karte das Licht (Ressource reserviert). Mit using var stellst du sicher: Selbst wenn du das Zimmer fluchtartig verlässt (z.B. durch eine Exception ausgelöst), schaltet sich der Strom beim Schließen der Tür garantiert automatisch ab (Dispose()).

📑 3. Cheat-Sheet: Exception & Resource Rules

Regel / Konzept Richtig (Enterprise Best Practice) Falsch (Anti-Pattern)
Exception Re-throwing throw; (Bewahrt Stack Trace) throw ex; (Zerstört ursprünglichen Stack Trace!)
Ausnahmen fangen Spezifische Typen (z.B. IOException) catch (Exception) {} (Verschluckt kritische Fehler)
IDisposable Lebenszyklus using var res = new Res(); Manuelles res.Dispose() ohne try-finally
ObjectDisposedException Prüfung ObjectDisposedException.ThrowIf(_disposed, this); Weiterarbeiten auf bereits freigegebenen Objekten

🎯 Aufgaben & Checkliste in Aufgabe.cs

💡 Clean Code Pro-Tipp: Argument Exceptions in C# 12

Nutze in modernem .NET die praktischen Helfer wie ArgumentNullException.ThrowIfNull(arg) und ArgumentOutOfRangeException.ThrowIfNegative(amount) für saubere, einzeilige Parameterprüfungen!

💻 In Web-IDE öffnen → Weiter zu C# 13: JSON & Dateien →