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


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

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

Причина

В инструкции 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 {inFile}.");
        }

        try
        {
            outStream = File.Open(outFile, FileMode.Open);
        }
        catch
        {
            Console.WriteLine($"Unable to open {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 {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 {outFile}.");
            throw;
        }
    }
}

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