CodeGym /Kurse /C# SELF /try-catch Syntax: Fehlerbehandlung

try-catch Syntax: Fehlerbehandlung

C# SELF
Level 13, Lektion 1
Verfügbar

1. Einführung

In einer perfekten Welt wäre der Code perfekt. Aber leider trifft selbst der ordentlichste Programmierer irgendwann auf unerwartete Situationen: Datei nicht gefunden, der User hat einen String statt einer Zahl eingegeben, das Netzwerk ist plötzlich weg oder aus der Datenbank kommt etwas zurück, das man so nicht erwartet hat.

Wenn man solche Probleme nicht abfängt, "crasht" das Programm einfach – manchmal mit einer mysteriösen Fehlermeldung und stack trace (Callstack). Das ist nicht das, was der User oder der zukünftige Support erwartet. Man muss lernen, solche Fehler zu "fangen" und darauf zu reagieren: das Programm sauber beenden, eine verständliche Nachricht anzeigen oder sogar die Situation direkt beheben.

try-catch ist der Weg, dem Compiler und der Runtime zu sagen: "Probier mal diesen Codeblock aus. Wenn was schiefgeht, keine Panik, lass mich das regeln!"

2. Grundlegender Syntax von try-catch

Die Struktur ist echt simpel:


try
{
    // Hier kommt gefährlicher (oder potenziell gefährlicher) Code rein
}
catch (ExceptionType variableName)
{
    // Hier steht, was passieren soll, wenn eine Exception vom Typ ExceptionType auftritt
}
Grundlegender Syntax von try-catch
  • Der try Block ist die "Gefahrenzone". Hier packst du alles rein, was potenziell "explodieren" könnte.
  • Der catch Block fängt Exceptions eines bestimmten Typs ab. Wenn im try eine Exception auftritt, springt das Programm sofort in den ersten passenden catch und der Code nach der "Problemstelle" im try wird nicht mehr ausgeführt.

Beispiel: einfache Exception-Behandlung

Nehmen wir an, unser Mini-Taschenrechner aus den letzten Vorlesungen kann jetzt Zahlen teilen. Aber der User könnte eine Null eingeben! Schauen wir mal, wie das ohne Fehlerbehandlung aussieht:

int a = 10;
int b = 0;
int result = a / b; // BUMM! System.DivideByZeroException
Console.WriteLine(result);

Das Programm beendet sich mit dem Fehler DivideByZeroException:

Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.

Jetzt "fixen" wir das mit try-catch:

int a = 10;
int b = 0;

try
{
    int result = a / b; // gefährliche Operation
    Console.WriteLine("Ergebnis der Division: " + result);
}
catch (DivideByZeroException ex)
{
    Console.WriteLine("Ups! Division durch Null ist nicht möglich: " + ex.Message);
}

Jetzt "crasht" das Programm nicht mehr. In der Konsole erscheint eine Nachricht, dass Division durch Null nicht geht:

Ups! Division durch Null ist nicht möglich: Attempted to divide by zero.

3. Wie funktioniert try-catch: Schritt für Schritt

Im try Block können beliebig viele Zeilen Code stehen. Wenn eine der Aktionen im Block eine Exception wirft, springt das Programm sofort in den nächsten passenden catch. Alles, was nach der Fehlerstelle im try steht, wird nicht mehr ausgeführt.

Schauen wir uns ein größeres Beispiel an:

try
{
    Console.WriteLine("Wir starten...");
    int[] zahlen = { 1, 2, 3 };
    Console.WriteLine(zahlen[1]);    // das ist ok
    Console.WriteLine(zahlen[5]);    // Fehler: Index außerhalb des Arrays
    Console.WriteLine("Diese Nachricht erscheint nicht mehr!");
}
catch (IndexOutOfRangeException)
{
    Console.WriteLine("Fehler: Versuch, auf ein nicht existierendes Array-Element zuzugreifen");
}

Die Ausgabe in der Konsole sieht so aus:

Wir starten...
2
Fehler: Versuch, auf ein nicht existierendes Array-Element zuzugreifen

Process finished with exit code 0.

Wie funktioniert dieses Programm?

  • Die Nachricht "Wir starten..." wird ausgegeben.
  • Dann versucht das Programm, das Element zahlen[1] auszugeben – das ist 2.
  • Bei zahlen[5] passiert der "Crash", es wird eine IndexOutOfRangeException geworfen.
  • Das Programm springt sofort in den catch Block und überspringt Console.WriteLine("Diese Nachricht erscheint nicht mehr!");
  • In der Konsole erscheint unsere Nachricht aus dem catch.

4. Kann man verschiedene Fehlertypen unterschiedlich behandeln?

Klar! Du kannst mehrere catch Blöcke angeben, um auf verschiedene Exception-Typen unterschiedlich zu reagieren. Das ist praktisch: Zum Beispiel, wenn eine Aktion mit Datei-Lesen zu tun hat (könnte FileNotFoundException werfen) und eine andere mit Division (könnte DivideByZeroException werfen).

try
{
    // Dein gefährlicher Code
}
catch (DivideByZeroException)
{
    Console.WriteLine("Fehler: Division durch Null");
}
catch (IndexOutOfRangeException)
{
    Console.WriteLine("Fehler: Index außerhalb des Array-Bereichs");
}
catch (Exception ex)
{
    Console.WriteLine("Irgendein unerwarteter Fehler: " + ex.Message);
}

Hier ist der letzte catch Block mit dem Typ Exception der "Universal-Fänger". Er fängt alle anderen Exceptions, die nicht zu den vorherigen passen. Aber Achtung: Wenn du ihn als ersten schreibst, kommen die anderen nie dran! Immer die "breiten" catch ans Ende stellen.

5. Wie sieht das Exception-Objekt aus?

Im catch Block kannst du optional eine Variable angeben – zum Beispiel catch (Exception ex). Sie enthält alle Infos zum Fehler: Nachricht, Typ, Stacktrace, innere Exceptions.

Hier ein kleines Beispiel:

try
{
    string? text = null;
    Console.WriteLine(text.Length); // Oha! NullReferenceException
}
catch (NullReferenceException ex)
{
    Console.WriteLine("Exception gefangen: " + ex.Message);
    Console.WriteLine("Stacktrace: " + ex.StackTrace);
}

So ein Ansatz ist Gold wert beim Debuggen von schwierigen Fehlern: Du siehst immer, wo und warum das Programm "gestolpert" ist.

6. Fehler abfangen und weitermachen

In echten, vor allem User-Anwendungen, ist ein Fehler nicht das Ende der Welt. Hat jemand einen falschen Dateipfad eingegeben – kann passieren. Kein Grund, das Programm gleich hysterisch neu zu starten. Stattdessen bitten wir ihn einfach, es nochmal zu versuchen.

Das folgende Beispiel zeigt einen einfachen, aber effektiven Ansatz: Wir packen das Datei-Lesen in eine Schleife, und wenn was schiefgeht, geben wir eine Fehlermeldung aus und bitten um einen neuen Versuch. Kein Stress, kein roter Bildschirm.

bool erfolg = false;
while (!erfolg)
{
    Console.Write("Dateiname eingeben: ");
    string dateiname = Console.ReadLine() ?? "";

    try
    {
        string inhalt = File.ReadAllText(dateiname);
        Console.WriteLine("Datei erfolgreich gelesen!");
        erfolg = true; // YES!
    }
    catch (FileNotFoundException)
    {
        Console.WriteLine("Fehler: Datei nicht gefunden. Versuch's nochmal.");
    }
}

Die Schlüsselidee hier: Nicht nur die Exception fangen, sondern sie auch sinnvoll behandeln: Wir lassen das Programm nicht abstürzen, sondern schalten in den Modus "nochmal, aber richtig". Der User bekommt einen klaren Hinweis, das Programm eine zweite Chance und du – Dankbarkeit und Respekt.

7. Typische Fehler beim Umgang mit try-catch

Fehler Nr. 1: Den ganzen Code in einen universellen try-catch packen.
Klingt verlockend – ein try, ein catch (Exception) und scheinbar ist "alles geschützt". Aber in Wirklichkeit verlierst du die Kontrolle. Es ist unklar, wo genau der Fehler passiert ist und auf welchen Fehler du eigentlich reagierst. Am Ende hast du statt Zuverlässigkeit totale Diagnose-Verluste.

Fehler Nr. 2: Exceptions fangen und nichts damit machen.
Ein Beispiel aus dem Leben:

try
{
    // irgendwas potenziell Gefährliches
}
catch
{
    // Schweigen...
}
Solcher Code sagt im Grunde: "Irgendwas ist schiefgelaufen... na und?" Das ist gefährlich: Das Programm läuft vielleicht im falschen Zustand weiter und du merkst nicht mal, dass es einen Fehler gab. Gib immer wenigstens eine Nachricht aus oder logge den Fehler. Keine leeren catch Blöcke!

Fehler Nr. 3: Zu allgemeine Exception-Typen fangen.
Wenn du Exception fängst, obwohl du weißt, dass z.B. FormatException oder FileNotFoundException auftreten können, nimmst du dir die Möglichkeit, auf das konkrete Problem sinnvoll zu reagieren. Je enger und genauer dein catch ist, desto vorhersehbarer und sauberer verhält sich dein Programm in ungewöhnlichen Situationen.

8. Wofür sollte man Exceptions NICHT verwenden?

Manche Anfänger nutzen Exceptions... als normalen Mechanismus zur Steuerung der Logik, zum Beispiel:

try
{
    if (x < 0) throw new Exception("x muss >= 0 sein");
}
catch (Exception)
{
    // Zustand zurücksetzen, weiterarbeiten...
}

So solltest du das nicht machen! Exceptions sind ein Tool für unerwartete, seltene Situationen (Dateilesefehler, Netzwerkprobleme usw.), nicht für normale User-Input-Validierung. Für solche Fälle nutze if/else und gib spezielle Werte zurück, wenn was nicht passt.

2
Aufgabe
C# SELF, Level 13, Lektion 1
Gesperrt
Division mit Fehlerbehandlung
Division mit Fehlerbehandlung
2
Aufgabe
C# SELF, Level 13, Lektion 1
Gesperrt
Verarbeitung ungültiger Zahleneingaben
Verarbeitung ungültiger Zahleneingaben
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION