Verwenden von Ausnahmen (C#-Programmierhandbuch)Using Exceptions (C# Programming Guide)

In C# werden Fehler im Programm zur Laufzeit mithilfe von sogenannten Ausnahmen durch das Programm weitergegeben.In C#, errors in the program at run time are propagated through the program by using a mechanism called exceptions. Ausnahmen werden von Code ausgelöst, der auf einen Fehler stößt. Sie werden von Code abgefangen, der den Fehler beheben kann.Exceptions are thrown by code that encounters an error and caught by code that can correct the error. Ausnahmen können durch die Common Language Runtime (CLR) von .NET Framework oder durch Code in einem Programm ausgelöst werden.Exceptions can be thrown by the .NET Framework common language runtime (CLR) or by code in a program. Sobald eine Ausnahme ausgelöst wird, wird sie in der Aufrufliste nach oben weitergegeben, bis eine catch-Anweisung für die Ausnahme gefunden wird.Once an exception is thrown, it propagates up the call stack until a catch statement for the exception is found. Nicht abgefangene Ausnahmen werden von einem generischen Ausnahmehandler behandelt, der vom System bereitgestellt wird, das ein Dialogfeld anzeigt.Uncaught exceptions are handled by a generic exception handler provided by the system that displays a dialog box.

Ausnahmen werden von Klassen dargestellt, die von Exception abgeleitet sind.Exceptions are represented by classes derived from Exception. Diese Klasse bestimmt den Typ der Ausnahme und enthält Eigenschaften, die über Details zur Ausnahme verfügen.This class identifies the type of exception and contains properties that have details about the exception. Das Auslösen einer Ausnahme umfasst das Erstellen einer Instanz einer von einer Ausnahme abgeleiteten Klasse, das optionale Konfigurieren von Eigenschaften der Ausnahme und das Auslösen des Objekts mithilfe des Schlüsselworts throw.Throwing an exception involves creating an instance of an exception-derived class, optionally configuring properties of the exception, and then throwing the object by using the throw keyword. Zum Beispiel:For example:


class CustomException : Exception
{
    public CustomException(string message)
    {
       
    }

}
private static void TestThrow()
{
    CustomException ex =
        new CustomException("Custom exception in TestThrow()");

    throw ex;
}

Nachdem eine Ausnahme ausgelöst wird, überprüft die Runtime die aktuelle Anweisung, um festzustellen, ob sie sich in einem try-Block befindet.After an exception is thrown, the runtime checks the current statement to see whether it is within a try block. Falls dies der Fall ist, werden alle mit dem try-Block verknüpften catch-Blöcke überprüft, um festzustellen, ob sie die Ausnahme abfangen können.If it is, any catch blocks associated with the try block are checked to see whether they can catch the exception. Catch-Blöcke geben normalerweise Ausnahmetypen an; wenn der Typ des catch-Blocks der gleiche Typ ist wie die Ausnahme oder die Basisklasse der Ausnahme, kann der catch-Block die Methode behandeln.Catch blocks typically specify exception types; if the type of the catch block is the same type as the exception, or a base class of the exception, the catch block can handle the method. Zum Beispiel:For example:

static void TestCatch()
{
    try
    {
        TestThrow();
    }
    catch (CustomException ex)
    {
        System.Console.WriteLine(ex.ToString());
    }
}

Wenn sich die Anweisung, die eine Ausnahme auslöst, nicht innerhalb eines try-Blocks befindet, oder der try-Block, der sie umfasst, über keinen übereinstimmenden catch-Block verfügt, überprüft die Runtime die aufrufende Methode auf eine try-Anweisung und catch-Blöcke.If the statement that throws an exception is not within a try block or if the try block that encloses it has no matching catch block, the runtime checks the calling method for a try statement and catch blocks. Die Runtime geht die Aufrufliste weiter nach oben durch und sucht nach einem kompatiblen catch-Block.The runtime continues up the calling stack, searching for a compatible catch block. Nachdem der catch-Block gefunden und ausgeführt wurde, wird die Steuerung an die nächste Anweisung nach diesem catch-Block weitergegeben.After the catch block is found and executed, control is passed to the next statement after that catch block.

Eine try-Anweisung kann mehr als einen catch-Block enthalten.A try statement can contain more than one catch block. Die erste catch-Anweisung, die die Ausnahme behandelt, wird ausgeführt; alle folgenden catch-Anweisungen werden ignoriert, selbst wenn sie kompatibel sind.The first catch statement that can handle the exception is executed; any following catch statements, even if they are compatible, are ignored. Daher sollten catch-Blöcke immer vom spezifischsten Element (oder am meisten abgeleiteten) zum am wenigsten spezifischen sortiert werden.Therefore, catch blocks should always be ordered from most specific (or most-derived) to least specific. Zum Beispiel:For example:

static void TestCatch2()
{
    System.IO.StreamWriter sw = null;
    try
    {
        sw = new System.IO.StreamWriter(@"C:\test\test.txt");
        sw.WriteLine("Hello");
    }

    catch (System.IO.FileNotFoundException ex)
    {
        // Put the more specific exception first.
        System.Console.WriteLine(ex.ToString());  
    }

    catch (System.IO.IOException ex)
    {
        // Put the less specific exception last.
        System.Console.WriteLine(ex.ToString());  
    }
    finally 
    {
        sw.Close();
    }

    System.Console.WriteLine("Done"); 
}

Bevor der catch-Block ausgeführt wird prüft die Runtime auf finally-Blöcke.Before the catch block is executed, the runtime checks for finally blocks. Finally-Blöcke ermöglichen dem Programmierer, mehrdeutige Zustände zu bereinigen, die möglicherweise von einem abgebrochenen try-Block übrig sind, oder externe Ressourcen freizugeben (z.B. Grafikhandles, Datenbankverbindungen oder Dateistreams), ohne auf Garbage Collector in der Runtime zum Finalisieren der Objekte zu warten.Finally blocks enable the programmer to clean up any ambiguous state that could be left over from an aborted try block, or to release any external resources (such as graphics handles, database connections or file streams) without waiting for the garbage collector in the runtime to finalize the objects. Zum Beispiel:For example:

static void TestFinally()
{
    System.IO.FileStream file = null;
    //Change the path to something that works on your machine.
    System.IO.FileInfo fileInfo = new System.IO.FileInfo(@"C:\file.txt");

    try
    {
        file = fileInfo.OpenWrite();
        file.WriteByte(0xF);
    }
    finally
    {
        // Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
        if (file != null)
        {
            file.Close();
        }
    }

    try
    {
        file = fileInfo.OpenWrite();
        System.Console.WriteLine("OpenWrite() succeeded");
    }
    catch (System.IO.IOException)
    {
        System.Console.WriteLine("OpenWrite() failed");
    }
}

Wenn WriteByte() eine Ausnahme auslöst, schlägt der Code im zweiten try-Block fehl, der versucht, die Datei erneut zu öffnen, wenn file.Close() nicht aufgerufen wird. Die Datei bleibt gesperrt.If WriteByte() threw an exception, the code in the second try block that tries to reopen the file would fail if file.Close() is not called, and the file would remain locked. Da finally-Blocke ausgeführt werden, selbst wenn eine Ausnahme ausgelöst wird, ermöglicht es der finally-Block im vorherigen Beispiel, dass die Datei korrekt geschlossen wird und trägt so zur Fehlervermeidung bei.Because finally blocks are executed even if an exception is thrown, the finally block in the previous example allows for the file to be closed correctly and helps avoid an error.

Wenn in der Aufrufliste kein kompatibler catch-Block gefunden wird, nachdem eine Ausnahme ausgelöst wird, tritt eine der folgenden Situationen auf:If no compatible catch block is found on the call stack after an exception is thrown, one of three things occurs:

  • Wenn die Ausnahme sich in einem Finalizer befindet, wird der Finalizer abgebrochen und der Basisfinalizer (sofern vorhanden) aufgerufen.If the exception is within a finalizer, the finalizer is aborted and the base finalizer, if any, is called.

  • Wenn die Aufrufliste einen statischen Konstruktor oder einen statischen Feldinitialisierer enthält, wird TypeInitializationException ausgelöst und die ursprüngliche Ausnahme der InnerException-Eigenschaft der neuen Ausnahme zugewiesen.If the call stack contains a static constructor, or a static field initializer, a TypeInitializationException is thrown, with the original exception assigned to the InnerException property of the new exception.

  • Wenn der Anfang des Threads erreicht wird, wird der Thread beendet.If the start of the thread is reached, the thread is terminated.

Siehe auchSee Also

C#-ProgrammierhandbuchC# Programming Guide
Ausnahmen und AusnahmebehandlungExceptions and Exception Handling