Freigeben über


Empfohlene Vorgehensweise für die Ausnahmebehandlung

Ein gut entworfener Satz von Fehlerbehandlungsblöcken kann einem Programm Stabilität verleihen und die Absturzgefahr mindern, da die Anwendung solche Fehler behandeln kann. Die folgende Auflistung enthält Vorschläge für die besten Methoden zur Ausnahmebehandlung:

  • Sie sollten sich klarmachen, wann ein try/catch-Block eingesetzt wird. Sie können zum Beispiel programmgesteuert auf einen wahrscheinlich auftretenden Fehlerzustand prüfen, ohne die Fehlerbehandlung zu verwenden. Dagegen ist es in anderen Fällen angebracht, die Fehlerbehandlung zu verwenden, um den Fehlerzustand abzufangen.

    Im folgenden Beispiel wird eine if-Anweisung verwendet, um zu überprüfen, ob eine Verbindung geschlossen ist. Sie können diese Methode verwenden, anstatt eine Ausnahme auszulösen, wenn die Verbindung nicht geschlossen ist.

       If conn.State <> ConnectionState.Closed Then
          conn.Close()
       End If
       if(conn.State != ConnectionState.Closed)
          conn.Close();
    

    Im folgenden Beispiel wird eine Ausnahme ausgelöst, wenn die Verbindung nicht geschlossen ist.

       Try
          conn.Close()
       Catch ex As InvalidOperationException
          'Do something with the error or ignore it.
       End Try
       try {
         conn.Close();
       }
       catch(InvalidOperationException ex) {
         //Do something with the error or ignore it.
       }
    

    Die Wahl der Methode hängt von der erwarteten Häufigkeit des Ereignisses ab. Ist das Ereignis ein wirklich seltener Fehler (wie z. B. ein unerwartetes Dateiende), ist eine Fehlerbehandlung besser, da normalerweise weniger Code ausgeführt wird. Kommt das Ereignis hingegen regelmäßig vor, ist die programmgesteuerte Methode der Fehlerüberprüfung angebrachter. Tritt in diesem Fall eine Ausnahme auf, nimmt die Ausnahmebehandlung mehr Zeit in Anspruch.

  • Umgeben Sie den Code, der potenzielle Ausnahmen generieren kann, mit try/finally-Blöcken, und fassen Sie alle catch-Anweisungen an einer Stelle zusammen. Auf diese Weise wird die Ausnahme durch die try-Anweisung generiert, durch die finally-Anweisung werden die Ressourcen geschlossen oder freigegeben, und durch die catch-Anweisung wird die Ausnahme von zentraler Stelle aus behandelt.

  • Ordnen Sie Ausnahmen in catch-Blöcken immer von der spezifischsten bis zur allgemeinsten an. Durch dieses Verfahren werden spezifische Ausnahmen behandelt, bevor sie an einen allgemeineren catch-Block übergeben werden.

  • Lassen Sie die Namen von Ausnahmeklassen auf das Wort "Exception" enden. Beispiel:

    Public Class EmployeeListNotFoundException
        Inherits Exception
    public class MyFileNotFoundException : Exception {
    }
    
  • Achten Sie beim Erstellen von benutzerdefinierten Ausnahmen darauf, dass Metadaten der Ausnahmen für remote ausgeführten Code verfügbar sind, und zwar auch bei Ausnahmen, die über verschiedene Anwendungsdomänen hinweg auftreten. Ein Beispiel: Anwendungsdomäne A erstellt Anwendungsdomäne B, die wiederum Code ausführt, der eine Ausnahme auslöst. Damit Anwendungsdomäne A die Ausnahme richtig abfangen und behandeln kann, muss A die Assembly finden, in der die von B ausgelöste Ausnahme enthalten ist. Wenn B eine Ausnahme auslöst, die in einer Assembly unter ihrer Anwendungsbasis enthalten ist, aber nicht unter der Anwendungsbasis von A, kann A die Ausnahme nicht finden. Daraufhin wird von der CLR die FileNotFoundException-Ausnahme ausgelöst. Um diese Situation zu vermeiden, haben Sie zwei Möglichkeiten, die Assembly mit den Ausnahmeinformationen bereitzustellen:

    • Legen Sie die Assembly in einer gemeinsamen Anwendungsbasis ab, die sich beide Anwendungsdomänen teilen.

      – oder –

    • Wenn die Domänen keine gemeinsame Anwendungsbasis verwenden, signieren Sie die Assembly, in der die Ausnahmeinformationen enthalten sind, mit einem starken Namen und legen sie in einem globalen Assemblycache ab.

  • Verwenden Sie in C# und C++ mindestens die drei allgemeinen Konstruktoren, wenn Sie eigene Ausnahmeklassen erstellen. Ein Beispiel finden Sie unter Verwenden benutzerdefinierter Ausnahmen.

  • Verwenden Sie in erster Linie die vordefinierten Ausnahmetypen. Definieren Sie neue Ausnahmetypen nur für programmgesteuerte Szenarien. Führen Sie eine neue Ausnahmeklasse ein, um Programmierern zu ermöglichen, darauf basierenden Code anders zu behandeln.

  • Leiten Sie benutzerdefinierte Ausnahmen für die meisten Anwendungen von der Exception-Klasse ab. Ursprünglich wurde davon ausgegangen, dass benutzerdefinierte Ausnahmen von der ApplicationException-Klasse abgeleitet werden sollten. In der Praxis hat sich dies jedoch nicht als bedeutender Vorteil erwiesen.

  • Schließen Sie eine lokalisierte Beschreibungszeichenfolge in jeder Ausnahme ein. Für Benutzer sichtbare Fehlermeldungen werden eher von der Beschreibungszeichenfolge der ausgelösten Ausnahme abgeleitet als von der Ausnahmeklasse.

  • Verwenden Sie grammatisch korrekte Fehlermeldungen, einschließlich Zeichensetzung am Satzende. Jeder Satz in einer Beschreibungszeichenfolge sollte mit einen Punkt beendet werden.

  • Bestimmen Sie Exception-Eigenschaften für programmgesteuerten Zugriff. Fügen Sie einer Ausnahme nur dann Informationen zusätzlich zur Beschreibungszeichenfolge bei, wenn es ein programmgesteuertes Szenario gibt, in dem dieser Zusatz sinnvoll ist.

  • Geben Sie bei sehr häufig auftretenden Fehlern NULL zurück. Beispielsweise gibt die File.Open-Methode NULL zurück, wenn eine Datei nicht gefunden wurde. Ist dagegen die Datei gesperrt, wird eine Ausnahme ausgelöst.

  • Entwerfen Sie Klassen, damit eine Ausnahme niemals während normaler Verwendung ausgelöst wird. Beispielsweise macht die FileStream-Klasse eine andere Möglichkeit verfügbar, um zu überprüfen, ob das Dateiende erreicht wurde. Dadurch wird die Ausnahme vermieden, die bei dem Versuch ausgelöst wird, nach Erreichen des Dateiendes weiterzulesen. Das folgende Beispiel zeigt, wie bis zum Dateiende gelesen wird.

    Class FileRead
       Sub Open()
          Dim stream As FileStream = _
                        File.Open("myfile.txt", FileMode.Open)
            Dim b As Byte
            Dim result As Integer
            ' ReadByte returns -1 at EOF.
            Do 
               result = stream.ReadByte()
               If result = -1 Then Exit Do
                b = CByte(result)
                ' Do something.
            Loop
            ' Call stream.Close() here or in another method.
        End Sub 'Open
    End Class 'FileRead
    class FileRead {
        public void Open() {
            FileStream stream = File.Open("myfile.txt", FileMode.Open);
            byte b;
            int result;
            // ReadByte returns -1 at EOF.
            while ((result = stream.ReadByte()) != -1) {
                b = (byte)result;
                // Do something.
                }
            // Call stream.Close() here or in another method.
        }
    }
    
  • Lösen Sie die InvalidOperationException-Ausnahme aus, wenn eine festgelegte Eigenschaft oder der Aufruf einer Methode aufgrund des aktuellen Objektzustands unangebracht ist.

  • Lösen Sie die ArgumentException-Ausnahme aus oder eine von ArgumentException abgeleitete Klasse, wenn ungültige Parameter übergeben wurden.

  • Die Stapelüberwachung beginnt mit der Anweisung, bei der die Ausnahme ausgelöst wurde, und endet mit der catch-Anweisung, mit der die Ausnahme abgefangen wird. Achten Sie auf diesen Umstand, wenn Sie eine throw-Anweisung platzieren.

  • Verwenden Sie Methoden zum Generieren von Ausnahmen. Es ist üblich, dass eine Klasse von unterschiedlichen Punkten in der Implementierung aus die gleiche Ausnahme auslöst. Verwenden Sie Hilfsmethoden, die eine Ausnahme erstellen und zurückgeben, um ausufernden Code zu vermeiden. Beispiel:

    Class File
       Private fileName As String
    
       Public Function Read(bytes As Integer) As Byte()
          If Not ReadFile(handle, bytes) Then
             Throw NewFileIOException()
          End If
       End Function 'Read
    
       Function NewFileIOException() As FileException
          Dim description As String = __unknown ' Build localized string, including fileName.
          Return New FileException(description) '
       End Function 'NewFileIOException
    End Class 'File
    class File {
        string fileName;
        public byte[] Read(int bytes) {
            if (!ReadFile(handle, bytes))
                throw NewFileIOException();
        }
        FileException NewFileIOException() {
            string description = // Build localized string, including fileName.
            return new FileException(description);
         }
    }
    

    Sie können auch den Ausnahmekonstruktor verwenden, um eine Ausnahme zu erstellen. Dies ist bei globalen Ausnahmeklassen wie der ArgumentException-Klasse eher angebracht.

  • Lösen Sie Ausnahmen aus, anstatt einen Fehlercode oder HRESULT zurückzugeben.

  • Löschen Sie Zwischenergebnisse, wenn Sie eine Ausnahme auslösen. Aufrufer sollten davon ausgehen können, dass keine Nebeneffekte auftreten, wenn eine Ausnahme von einer Methode ausgelöst wird.

Siehe auch

Weitere Ressourcen

Behandeln und Auslösen von Ausnahmen