Поделиться через


Обработка исключений

Обновлен: Ноябрь 2007

Следующие рекомендации помогут эффективно обрабатывать исключения при разработке библиотеки.

Не обрабатывайте ошибки, перехватывая неспецифичные исключения, такие как System.Exception, System.SystemException и т.п. в коде .NET Framework.

Можно перехватывать исключения для повторной генерации или передачи исключения другому потоку. В следующем примере кода демонстрируется неправильная обработка исключения.

Public Class BadExceptionHandlingExample1

    Public Sub DoWork()
        ' Do some work that might throw exceptions.
    End Sub

    Public Sub MethodWithBadHandler()
        Try
            DoWork()
        Catch e As Exception
            ' Handle the exception and 
            ' continue executing.
        End Try
    End Sub
End Class
public class BadExceptionHandlingExample1
{
    public void DoWork()
    {
        // Do some work that might throw exceptions.
    }
    public void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception e)
        {
            // Handle the exception and
            // continue executing.
        }
    }
}

Избегайте обработки ошибок, перехватывая неспецифичные исключения, такие как System.Exception, System.SystemException и т.п. в коде приложения. Существуют случаи, когда обработка ошибок в приложении приемлема, но таких случаев немного.

Приложение не должно обрабатывать исключения, которые могут привести к неожиданному или нерабочему состоянию. Если вы не можете предусмотреть все возможные причины генерации исключений, то для того, чтобы не допустить зависания приложения из-за неверного кода, следует позволить приложению завершиться вместо обработки исключения.

Не игнорируйте специальные исключения при перехвате для передачи исключений.

Вместо создания списков специальных исключений в операторах catch, следует перехватывать только те исключения, которые могут быть успешно обработаны. Исключения, которые невозможно обработать, не следует относить к особым случаям обработчиков неспецифичных исключений. В следующем примере кода показана неправильная проверка специальных исключений для повторной генерации.

Public Class BadExceptionHandlingExample2

    Public Sub DoWork()
        ' Do some work that might throw exceptions.
    End Sub

    Public Sub MethodWithBadHandler()
        Try
            DoWork()
        Catch e As Exception
            If TypeOf e Is StackOverflowException Or _
               TypeOf e Is OutOfMemoryException Then
                Throw
            End If
        End Try
    End Sub
End Class
public class BadExceptionHandlingExample2
{
    public void DoWork()
    {
        // Do some work that might throw exceptions.
    }
    public void MethodWithBadHandler()
    {
        try
        {
            DoWork();
        }
        catch (Exception e)
        {
            if (e is StackOverflowException ||
                e is OutOfMemoryException)
                throw;
            // Handle the exception and
            // continue executing.
        }
    }
}

Рекомендуется перехватывать специфичные исключения, когда Вы понимаете, почему они генерируются в данном контексте.

Следует перехватывать только те исключения, причины которых можно устранить. Например, FileNotFoundException, который получается в результате попытки открыть несуществующий файл, может быть обработан приложением, так как оно может сообщить о проблеме пользователю и позволить пользователю указать другое имя файла или создать новый файл. Запрос на открытие файла, генерирующий ExecutionEngineException, не должен обрабатываться, так как причина генерации исключения неопределенна и приложение не может гарантировать безопасного продолжения работы.

Не злоупотребляйте перехватами. Часто исключениям следует позволять переходить вверх по стеку вызовов.

Перехват исключений, которые вы не можете успешно обработать, скрывает информацию, критичную для отладки.

Используйте "try-finally" и избегайте использования "try-catch" для игнорирования исключения. В хорошо написанном коде обработки исключения "try-finally" встречается намного чаще, чем "try-catch".

Целью оператора catch является обработка исключений (например, регистрация нефатальных ошибок). Целью оператора finally является выполнение кода независимо от того, было ли генерировано исключение. При размещении дорогих или ограниченных ресурсов, таких как соединения с базами данных или потоками, помещайте код в блок finally.

Предпочтительнее использование пустой генерации при захвате и повторной генерации исключения. Это лучший способ сохранить стек вызова исключений.

В следующем примере кода показан метод генерации исключения. Этот метод используется в следующих примерах.

Public Sub DoWork(ByVal anObject As Object)
    ' Do some work that might throw exceptions.
    If (anObject = Nothing) Then
        Throw New ArgumentNullException("anObject", "Specify a non-null argument.")
    End If
    ' Do work with o.
End Sub
public void DoWork(Object anObject)
{
    // Do some work that might throw exceptions.
    if (anObject == null)
    {
        throw new ArgumentNullException("anObject",
            "Specify a non-null argument.");
    }
    // Do work with o.
}

В следующем примере кода показан перехват исключения и неправильное его указание при повторной генерации. В результате стек указывает на повторную генерацию как на место ошибки, вместо того чтобы указывать на метод DoWork.

Public Sub MethodWithBadCatch(ByVal anObject As Object)
    Try
        DoWork(anObject)

    Catch e As ArgumentNullException
        System.Diagnostics.Debug.Write(e.Message)
        ' This is wrong.
        Throw e
        ' Should be this:
        ' throw
    End Try
End Sub

public void MethodWithBadCatch(Object anObject)
{
    try
    {
        DoWork(anObject);
    }
    catch (ArgumentNullException e)
    {
       System.Diagnostics.Debug.Write(e.Message);
       // This is wrong.
       throw e;
       // Should be this:
       // throw;
    }
}

Не обрабатывайте несовместимые со средой CLS исключения (исключения, которые не являются производными от System.Exception) с использованием безаргументного "catch"-блока. Языки, поддерживающие исключения, которые не являются производными от Exception, свободно обрабатывают эти несовместимые со средой CLS исключения.

.NET Framework версии 2.0 заключает несовместимые со средой CLS исключения в класс, производный от Exception.

Охраняется авторским правом Copyright 2005 Microsoft Corporation. Все права защищены.

Охраняется авторским правом Copyright Addison-Wesley Corporation. Все права защищены.

Дополнительные сведения о руководствах по разработке см. в книге "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries", Krzysztof Cwalina and Brad Abrams, Addison-Wesley, 2005.

См. также

Другие ресурсы

Руководство по разработке библиотек классов

Правила разработки исключений