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


Создание исключений

Исключения генерируются, когда член не может успешно выполняться. Это называется ошибкой выполнения. Например, если метод Connect не может установить соединение с определенным удаленным сокетом, это является ошибкой выполнения, в результате чего генерируется исключение.

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

Не возвращайте коды ошибок. Исключения являются первичным средством сообщения об ошибках в .NET Framework.

В разделе Правила разработки исключений обсуждаются преимущества использования исключений.

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

Рекомендуется завершать процесс вызовом System.Environment.FailFast(System.String) (функция .NET Framework версии 2.0) вместо генерации исключения, если Ваш код не может безопасно выполняться в данной ситуации.

По возможности, не следует использовать исключения для нормального потока управления. За исключением ошибок системы и операций с потенциальным состоянием гонки, разработчики .NET Framework должны проектировать API так, чтобы пользователи могли писать код без генерации исключений. Например, можно обеспечить путь для проверки предварительных условий до вызова члена так, чтобы пользователи могли написать код, не используя генерацию исключений.

В следующем примере кода показана проверка для предотвращения генерации исключений, когда строка сообщения является null (Nothing в Visual Basic).

Public Class Doer

    ' Method that can potential throw exceptions often.
    Public Shared Sub ProcessMessage(ByVal message As String)
        If (message = Nothing) Then
            Throw New ArgumentNullException("message")
        End If
    End Sub

    ' Other methods...
End Class

Public Class Tester

    Public Shared Sub TesterDoer(ByVal messages As ICollection(Of String))
        For Each message As String In messages
            ' Test to ensure that the call 
            ' won't cause the exception.
            If (Not (message) Is Nothing) Then
                Doer.ProcessMessage(message)
            End If
        Next
    End Sub
End Class
public class Doer
{
    // Method that can potential throw exceptions often.
    public static void ProcessMessage(string message)
    {
        if (message == null)
        {
            throw new ArgumentNullException("message");
        }
    }
    // Other methods...
}

public class Tester
{
    public static void TesterDoer(ICollection<string> messages)
    {
        foreach (string message in messages)
        {
            // Test to ensure that the call
            // won't cause the exception.
            if (message != null)
            {
                Doer.ProcessMessage(message);
            }
        }
    }
}
public ref class Doer
{
public:
    // Method that can potential throw exceptions often.
    static void ProcessMessage(String^ message)
    {
        if (message == nullptr)
        {
            throw gcnew ArgumentNullException("message");
       }
    }
    // Other methods...
};

public ref class Tester
{
public:
    static void TesterDoer(ICollection<String^>^ messages)
    {
        for each (String^ message in messages)
        {
            // Test to ensure that the call
            // won't cause the exception.
            if (message != nullptr)
            {
                Doer::ProcessMessage(message);
            }
        }
    }
};

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

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

Документируйте все исключения, генерируемые публично вызываемыми членами из-за проблем нарушения контракта члена (а не системной ошибки), и рассматривайте их как часть вашего контракта. Исключения, являющиеся частью контракта, не должны изменяться от версии к версии.

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

Например, не определяйте методов, подобных следующему:

Private Function ParseUri(ByVal uriValue As String, ByVal throwOnError As Boolean) As Uri
Uri ParseUri(string uriValue, bool throwOnError)
Uri^ ParseUri(String^ uriValue, bool throwOnError)

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

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

Рекомендуется использовать методы конструктора исключений. Обычно одно и то же исключение генерируется из различных мест. Чтобы избежать разбухания кода, используйте методы "helper", создающие исключения и затем инициализирующие их свойства.

Метод "helper" не должен генерировать исключение, иначе трассировщик стека неверно отобразит стек вызовов, который привел к исключению.

Не генерируйте исключения из блоков фильтрации исключений. Когда фильтр исключений распознает исключение, исключение захватывается средой CLR и фильтр возвращает значение "false". Этот алгоритм неотличим от явного возврата фильтром значения "false" при выполнении фильтра, поэтому этот случай крайне сложен для отладки.

Некоторые языки, такие как C#, не поддерживают фильтры исключений.

Избегайте явной генерации исключений из блоков "finally". Приемлемы явно генерированные исключения, которые являются результатом вызовов методов.

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

Фрагменты — © Addison-Wesley Corporation. Все права защищены.

Для дополнительной информации о разработке руководящих принципов, смотрите "руководства по разработке рамок: Конвенций, идиомы и шаблоны для повторного использования.NET библиотек"книга, Кшиштоф Cwalina и Брэд Абрамс, опубликованных Addison-Wesley, 2005 года.

См. также

Основные понятия

Выбор правильного типа создаваемого исключения

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

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

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