Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In C# werden Fehler im Programm zur Laufzeit mithilfe eines Mechanismus, der als Ausnahmen bezeichnet wird, über das Programm verteilt. Ausnahmen werden von Code ausgelöst, der auf einen Fehler stößt. Sie werden von Code abgefangen, der den Fehler beheben kann. Ausnahmen können durch die .NET-Runtime oder durch Code in einem Programm ausgelöst werden. Sobald eine Ausnahme ausgelöst wird, breitet sie sich durch den Aufrufstapel nach oben aus, bis eine catch
Anweisung für die Ausnahme gefunden wird. Nicht abgefangene Ausnahmen werden von einem allgemeinen Ausnahmebehandler behandelt, der vom System bereitgestellt wird und einen Dialogfenster anzeigt.
Ausnahmen werden durch Klassen repräsentiert, die von Exception abgeleitet sind. Diese Klasse identifiziert den Ausnahmetyp und enthält Eigenschaften, die Details zur Ausnahme enthalten. Das Auslösen einer Ausnahme umfasst das Erstellen einer Instanz einer ausnahme abgeleiteten Klasse, optional das Konfigurieren von Eigenschaften der Ausnahme und das anschließende Auslösen des Objekts mithilfe des throw
Schlüsselworts. Beispiel:
class CustomException : Exception
{
public CustomException(string message)
{
}
}
private static void TestThrow()
{
throw new CustomException("Custom exception in TestThrow()");
}
Nachdem eine Ausnahme ausgelöst wurde, überprüft die Laufzeit die aktuelle Anweisung, um festzustellen, ob sie sich innerhalb eines try
Blocks befindet. Wenn dies der Fall ist, werden alle catch
zugeordneten try
Blöcke überprüft, um festzustellen, ob sie die Ausnahme abfangen können.
Catch
Blöcke geben in der Regel Ausnahmetypen an; wenn der Typ des catch
Blocks derselbe Typ wie die Ausnahme ist oder eine Basisklasse der Ausnahme, kann der catch
Block die Methode behandeln. Beispiel:
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 wenn der try
eingeschlossene Block keinen übereinstimmenden catch
Block aufweist, überprüft die Laufzeit die aufrufende Methode auf eine try
Anweisung und catch
Blöcke. Die Laufzeit durchläuft den Aufrufstapel weiter und sucht nach einem kompatiblen catch
-Block. Nachdem der catch
Block gefunden und ausgeführt wurde, wird das Steuerelement an die nächste Anweisung nach diesem catch
Block übergeben.
Eine try
Anweisung kann mehr als einen catch
Block enthalten. Die erste catch
Anweisung, die die Ausnahme behandeln kann, wird ausgeführt. Alle folgenden catch
Anweisungen, auch wenn sie kompatibel sind, werden ignoriert. Sortieren Sie Catch-Blöcke immer vom spezifischsten (oder am meisten abgeleiteten) zum am wenigsten spezifischen Element. Beispiel:
using System;
using System.IO;
namespace Exceptions
{
public class CatchOrder
{
public static void Main()
{
try
{
using (var sw = new StreamWriter("./test.txt"))
{
sw.WriteLine("Hello");
}
}
// Put the more specific exceptions first.
catch (DirectoryNotFoundException ex)
{
Console.WriteLine(ex);
}
catch (FileNotFoundException ex)
{
Console.WriteLine(ex);
}
// Put the least specific exception last.
catch (IOException ex)
{
Console.WriteLine(ex);
}
Console.WriteLine("Done");
}
}
}
Bevor der catch
Block ausgeführt wird, sucht die Laufzeit nach finally
Blöcken.
Finally
Blöcke ermöglichen es dem Programmierer, alle mehrdeutigen Zustände zu bereinigen, die von einem abgebrochenen try
Block übrig bleiben könnten, oder externe Ressourcen (z. B. Grafikhandles, Datenbankverbindungen oder Dateidatenströme) freizugeben, ohne auf den Garbage Collector in der Laufzeit zu warten, um die Objekte abzuschließen. Beispiel:
static void TestFinally()
{
FileStream? file = null;
//Change the path to something that works on your machine.
FileInfo fileInfo = new System.IO.FileInfo("./file.txt");
try
{
file = fileInfo.OpenWrite();
file.WriteByte(0xF);
}
finally
{
// Closing the file allows you to reopen it immediately - otherwise IOException is thrown.
file?.Close();
}
try
{
file = fileInfo.OpenWrite();
Console.WriteLine("OpenWrite() succeeded");
}
catch (IOException)
{
Console.WriteLine("OpenWrite() failed");
}
}
Falls WriteByte()
eine Ausnahme ausgelöst, schlägt der Code im zweiten try
Block, der versucht, die Datei erneut zu öffnen, fehl, sofern file.Close()
nicht aufgerufen wird, und die Datei bleibt gesperrt. Da finally
Blöcke auch dann ausgeführt werden, wenn eine Ausnahme ausgelöst wird, lässt der finally
Block im vorherigen Beispiel zu, dass die Datei korrekt geschlossen und ein Fehler vermieden wird.
Wenn kein kompatibler catch
Block im Aufrufstapel gefunden wird, nachdem eine Ausnahme ausgelöst wurde, tritt eins von drei Elementen auf:
- Wenn sich die Ausnahme innerhalb eines Finalizers befindet, wird der Finalizer abgebrochen, und der Basis-Finalizer wird (falls vorhanden) aufgerufen.
- Wenn der Aufrufstapel einen statischen Konstruktor oder einen Initialisierer für statische Felder enthält, wird ein TypeInitializationException geworfen, wobei die ursprüngliche Ausnahme der InnerException-Eigenschaft der neuen Ausnahme zugewiesen wird.
- Wenn der Start des Threads erreicht ist, wird der Thread beendet.