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


CA1031: не перехватывайте типы общих исключений

Свойство Значение
Идентификатор правила CA1031
Заголовок Не перехватывайте типы общих исключений
Категория Проектирование
Исправление является критическим или не критическим Не критическое
Включен по умолчанию в .NET 9 No

Причина

В инструкции catch перехватывается общее исключение, такое как System.Exception или System.SystemException, или используется общее предложение catch, такое как catch().

По умолчанию это правило помечает только общие типы исключений, но это можно настроить.

Описание правила

Общие исключения не должны перехватываться.

Устранение нарушений

Чтобы исправить нарушение этого правила, следует перехватить более конкретное исключение или повторно вызвать общее исключение в последнем операторе блока catch.

Когда лучше отключить предупреждения

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

Примечание.

Начиная с .NET Framework 4 общеязыковая среда выполнения (CLR) больше не поставляет исключения поврежденного состояния, происходящие в операционной системе и управляемом коде, такие как нарушения прав доступа в Windows, для обработки управляемым кодом. Если вы хотите компилировать приложение в .NET Framework 4 или более поздней версии и поддерживать обработку исключений поврежденного состояния, можно применить атрибут HandleProcessCorruptedStateExceptionsAttribute к методу, обрабатывающему исключение поврежденного состояния.

Настройка кода для анализа

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

Этот параметр можно настроить только для этого правила, для всех правил, к которым он применяется, или для всех правил в этой категории (конструкторе), к которым она применяется. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.

Недопустимые имена типов исключений

Вы можете настроить, какие типы исключений запрещены для перехвата. Например, чтобы указать, что правило должно помечать обработчики catch флагом NullReferenceException, добавьте следующую пару "ключ-значение" в файл .editorconfig в своем проекте:

dotnet_code_quality.CA1031.disallowed_symbol_names = NullReferenceException

Допустимые форматы имен типов в значении параметра (разделенные |):

Примеры:

Значение параметра Итоги
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType Соответствует всем символам с именем ExceptionType в компиляции.
dotnet_code_quality.CA1031.disallowed_symbol_names = ExceptionType1|ExceptionType2 Соответствует всем символам с именем ExceptionType1 или ExceptionType2 в компиляции.
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS.ExceptionType Соответствует определенным типам с именем "ExceptionType" и заданным полным именем.
dotnet_code_quality.CA1031.disallowed_symbol_names = T:NS1.ExceptionType1|T:NS1.ExceptionType2 Соответствует типам с именами ExceptionType1 и ExceptionType2 с соответствующими полными именами.

Эти параметры можно настроить только для этого правила, для всех правил, к которым она применяется, или для всех правил в этой категории (конструктор), к которым она применяется. Дополнительные сведения см. в статье Параметры конфигурации правила качества кода.

Пример

В следующем примере показан тип, который нарушает правило, и тип, который правильно реализует блок catch.

Imports System
Imports System.IO

Namespace ca1031

    ' Creates two violations of the rule.
    Public Class GenericExceptionsCaught

        Dim inStream As FileStream
        Dim outStream As FileStream

        Sub New(inFile As String, outFile As String)

            Try
                inStream = File.Open(inFile, FileMode.Open)
            Catch ex As SystemException
                Console.WriteLine("Unable to open {0}.", inFile)
            End Try

            Try
                outStream = File.Open(outFile, FileMode.Open)
            Catch
                Console.WriteLine("Unable to open {0}.", outFile)
            End Try

        End Sub

    End Class

    Public Class GenericExceptionsCaughtFixed

        Dim inStream As FileStream
        Dim outStream As FileStream

        Sub New(inFile As String, outFile As String)

            Try
                inStream = File.Open(inFile, FileMode.Open)

                ' Fix the first violation by catching a specific exception.
            Catch ex As FileNotFoundException
                Console.WriteLine("Unable to open {0}.", inFile)
                ' For functionally equivalent code, also catch the
                ' remaining exceptions that may be thrown by File.Open
            End Try

            Try
                outStream = File.Open(outFile, FileMode.Open)

                ' Fix the second violation by re-throwing the generic 
                ' exception at the end of the catch block.
            Catch
                Console.WriteLine("Unable to open {0}.", outFile)
                Throw
            End Try

        End Sub

    End Class

End Namespace
// Creates two violations of the rule.
public class GenericExceptionsCaught
{
    FileStream? inStream;
    FileStream? outStream;

    public GenericExceptionsCaught(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }
        catch (SystemException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        }

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
        }
    }
}

public class GenericExceptionsCaughtFixed
{
    FileStream? inStream;
    FileStream outStream;

    public GenericExceptionsCaughtFixed(string inFile, string outFile)
    {
        try
        {
            inStream = File.Open(inFile, FileMode.Open);
        }

        // Fix the first violation by catching a specific exception.
        catch (FileNotFoundException)
        {
            Console.WriteLine("Unable to open {0}.", inFile);
        };

        // For functionally equivalent code, also catch 
        // remaining exceptions that may be thrown by File.Open

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }

        // Fix the second violation by rethrowing the generic 
        // exception at the end of the catch block.
        catch
        {
            Console.WriteLine("Unable to open {0}.", outFile);
            throw;
        }
    }
}

CA2200: следует повторно вызывать исключение для сохранения сведений о стеке