CA1064: исключения должны быть открытыми

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

Причина

Исключение, не являющееся общим, наследуется непосредственно от Exception, SystemException или ApplicationException.

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

Внутреннее исключение видимо только в своей внутренней области. После выхода исключения за пределы внутренней области для перехвата исключения можно использовать только базовое исключение. Если внутреннее исключение унаследовано от Exception, SystemException или ApplicationException, внешний код не имеет достаточных данных для обработки этого исключения.

Но если в коде есть общее исключение, которое позже используется в качестве основы для внутреннего исключения, разумно предположить, что код сможет сделать что-то осмысленное с помощью базового исключения. Общее исключение будет содержать больше сведений, чем предоставляется Exception, SystemException или ApplicationException.

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

Сделайте исключение общим или создайте производное внутреннее исключение из общего исключения, которое не является Exception, SystemException или ApplicationException.

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

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

Отключение предупреждений

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

#pragma warning disable CA1064
// The code that's violating the rule is on this line.
#pragma warning restore CA1064

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

[*.{cs,vb}]
dotnet_diagnostic.CA1064.severity = none

Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.

Пример

Это правило срабатывает в первом примере метода FirstCustomException, так как класс исключения является производным непосредственно от Exception, и это внутренний класс. Правило не срабатывает для класса SecondCustomException, так как, хотя этот класс тоже производный от Exception, он объявлен как общий. Для третьего класса правило тоже не срабатывает, так как этот класс не является производным непосредственно от System.Exception, System.SystemException или System.ApplicationException.

// Violates this rule
[Serializable]
internal class FirstCustomException : Exception
{
    internal FirstCustomException()
    {
    }

    internal FirstCustomException(string message)
        : base(message)
    {
    }

    internal FirstCustomException(string message, Exception innerException)
        : base(message, innerException)
    {
    }

    protected FirstCustomException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

// Does not violate this rule because
// SecondCustomException is public
[Serializable]
public class SecondCustomException : Exception
{
    public SecondCustomException()
    {
    }

    public SecondCustomException(string message)
        : base(message)
    {

    }

    public SecondCustomException(string message, Exception innerException)
        : base(message, innerException)
    {
    }

    protected SecondCustomException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}

// Does not violate this rule because
// ThirdCustomException it does not derive directly from
// Exception, SystemException, or ApplicationException
[Serializable]
internal class ThirdCustomException : SecondCustomException
{
    internal ThirdCustomException()
    {
    }

    internal ThirdCustomException(string message)
        : base(message)
    {
    }

    internal ThirdCustomException(string message, Exception innerException)
        : base(message, innerException)
    {
    }


    protected ThirdCustomException(SerializationInfo info, StreamingContext context)
        : base(info, context)
    {
    }
}