Ausnahmebehandlung (C#-Programmierhandbuch)

Ein try-Block wird von C#-Programmierern verwendet, um Code zu partitionieren, der von einer Ausnahme betroffen sein könnte. Zugeordnete catch-Blöcke werden verwendet, um die sich ergebenden Ausnahmen zu behandeln. Ein finally-Block enthält Code, der ausgeführt wird, unabhängig davon, ob eine Ausnahme im try-Block ausgelöst wird, z.B. das Freigeben von Ressourcen, die im try-Block zugeordnet werden. Ein try-Block erfordert einen oder mehrere zugeordnete catch-Blöcke oder ein finally-Block oder beides.

Die folgenden Beispiele zeigen eine try-catch-Anweisung eine try-finally-Anweisung und eine try-catch-finally-Anweisung.

try
{
    // Code to try goes here.
}
catch (SomeSpecificException ex)
{
    // Code to handle the exception goes here.
    // Only catch exceptions that you know how to handle.
    // Never catch base class System.Exception without
    // rethrowing it at the end of the catch block.
}
try
{
    // Code to try goes here.
}
finally
{
    // Code to execute after the try block goes here.
}
try
{
    // Code to try goes here.
}
catch (SomeSpecificException ex)
{
    // Code to handle the exception goes here.
}
finally
{
    // Code to execute after the try (and possibly catch) blocks 
    // goes here.
}

Ein try-Block ohne einen catch- oder finally-Block verursachen einen Compilerfehler.

catch-Blöcke

Ein catch-Block kann den Typ der Ausnahme angeben, die abgefangen werden soll. Die Typspezifikation wird einen Ausnahmefilter aufrufen. Der Typ der Ausnahme sollte von Exception abgeleitet werden. Im Allgemeinen sollten Sie Exception nicht als Ausnahmefilter angeben, sofern Sie nicht entweder alle Ausnahmen behandeln können, die möglicherweise im try-Block ausgelöst werden, oder Sie nicht eine throw-Anweisung am Ende des catch-Blocks eingeschlossen haben.

Mehrere catch-Blöcke mit verschiedenen Ausnahmefiltern können miteinander verkettet werden. Die catch-Blöcke werden von oben nach unten in Ihrem Code überprüft, aber nur ein catch-Block wird für jede Ausnahme, die ausgelöst wird, ausgeführt. Der erste catch-Block, der den exakten Typ oder eine Basisklasse der ausgelösten Ausnahme angibt, wird ausgeführt. Wenn kein catch-Block einen passenden Ausnahmefilter angibt, wird ein catch-Block, der über keinen Filter verfügt, ausgewählt, wenn einer in der Anweisung vorhanden ist. Es ist wichtig, catch-Blöcke mit den spezifischsten (d.h. am stärksten abgeleiteten) Ausnahmetypen als erstes zu positionieren.

Sie sollten die Ausnahmen abfangen, wenn Folgendes zutrifft:

  • Sie verstehen, warum die Ausnahme ausgelöst werden kann, und Sie können eine bestimmte Wiederherstellung implementieren, wie z.B. den Benutzer auffordern, einen neuen Dateinamen einzugeben, wenn Sie ein Objekt FileNotFoundException abfangen.

  • Sie können eine neue und spezifischere Ausnahme erstellen und auslösen.

    int GetInt(int[] array, int index)
    {
        try
        {
            return array[index];
        }
        catch(System.IndexOutOfRangeException e)
        {
            throw new System.ArgumentOutOfRangeException(
                "Parameter index is out of range.", e);
        }
    }
    
  • Sie möchten eine Ausnahme teilweise behandeln, bevor Sie sie für eine zusätzliche Behandlung weitergeben. Im folgenden Beispiel wird ein catch-Block verwendet, um dem Fehlerprotokoll einen Eintrag hinzufügen, bevor die Ausnahme erneut ausgelöst wird.

    try
    {
        // Try to access a resource.
    }
    catch (System.UnauthorizedAccessException e)
    {
        // Call a custom error logging procedure.
        LogError(e);
        // Re-throw the error.
        throw;     
    }
    

Finally-Blöcke

Mit einem finally-Block können Sie Aktionen bereinigen, die in einem try-Block ausgeführt werden. Falls vorhanden, wird der finally-Block zuletzt ausgeführt, nach dem try-Block und jedem übereinstimmenden catch Block. Ein finally-Block wird immer ausgeführt, unabhängig davon, ob eine Ausnahme ausgelöst wird oder ein catch-Block gefunden wird, der mit dem Ausnahmetyp übereinstimmt.

Der finally-Block kann zum Freigeben von Ressourcen verwendet werden, wie z.B. Dateistreams, Datenbankverbindungen und Grafikhandles, ohne Warten auf den Garbage Collector in der Laufzeit, um die Objekte zu beenden. Weitere Informationen finden Sie unter using-Anweisung.

Im folgenden Beispiel wird der finally-Block verwendet, um eine Datei, die im try-Block geöffnet ist, zu schließen. Beachten Sie, dass der Status des Dateihandles überprüft wird, bevor die Datei geschlossen wird. Wenn der try-Block die Datei nicht öffnen kann, verfügt das Dateihandle immer noch über den Wert null, und der finally-Block versucht nicht, es zu schließen. Alternativ schließt der finally-Block die geöffnete Datei, wenn die Datei im try-Block erfolgreich geöffnet wird.

System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo("C:\\file.txt");
try
{
    file = fileinfo.OpenWrite();
    file.WriteByte(0xF);
}
finally
{
    // Check for null because OpenWrite might have failed.
    if (file != null)
    {
        file.Close();
    }
}

C#-Programmiersprachenspezifikation

Weitere Informationen erhalten Sie unter C#-Sprachspezifikation. Die Sprachspezifikation ist die verbindliche Quelle für die Syntax und Verwendung von C#.

Siehe auch

C#-Referenz
C#-Programmierhandbuch
Ausnahmen und Ausnahmebehandlung
try-catch
try-finally
try-catch-finally
Using-Anweisung