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


CA2208: правильно создавайте экземпляры аргументов исключений

Свойство Значение
Идентификатор правила CA2208
Заголовок Правильно создавайте экземпляры исключений аргументов
Категория Использование
Исправление является критическим или не критическим Не критическое
Включен по умолчанию в .NET 10 Как предложение

Причина

Если метод имеет параметр и создает тип исключения, который является ArgumentException или производным от него, ожидается вызов конструктора, корректно принимающего параметр paramName. Возможные причины ошибки:

  • Вызов выполняется к конструктору по умолчанию (без параметров) типа исключения, который является производным или производным от него, который также имеет конструктор, ArgumentExceptionparamName принимаюющий параметр.
  • Неверный строковый аргумент передается в параметризованный конструктор типа исключения, который является ArgumentException или производным от него. Например, paramName аргумент не соответствует имени одного из параметров метода.
  • Имя параметра передается для message аргумента конструктора типа исключения, который является или происходит от ArgumentException.

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

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

Сигнатуры конструкторов строк класса ArgumentException и производных типов не соответствуют положению параметров message и paramName. Убедитесь, что эти конструкторы вызываются с правильными строковыми аргументами. Эти сигнатуры представлены ниже:

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

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

Совет

В Visual Studio доступно исправление кода для неправильно позиционированных имен параметров. Чтобы использовать его, поместите курсор в строку предупреждения и нажмите клавиши CTRL+ (период). Выберите Переключить порядок аргументов в списке.

Исправление кода для CA2208 — замена аргументов.

Если в метод ArgumentException(String) передается имя параметра, а не сообщение, исправление предоставляет параметр для переключения на конструктор с двумя аргументами.

Исправление кода для CA2208 — переключение на конструктор с двумя аргументами.

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

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

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

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

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

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

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

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

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

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

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

Включение определенных контактных зон API

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

dotnet_code_quality.CAXXXX.api_surface = private, internal

Заметка

Замените XXXX частью CAXXXX идентификатором применимого правила.

По умолчанию правило CA2208 применяется ко всем областям API (общедоступные, внутренние и частные).

Пример

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

public class Book
{
    public Book(string title)
    {
        Title = title ??
            throw new ArgumentNullException("All books must have a title.", nameof(title));
    }

    public string Title { get; }
}
Public Class Book

    Private ReadOnly _Title As String

    Public Sub New(ByVal title As String)
        ' Violates this rule (constructor arguments are switched)            
        If (title Is Nothing) Then
            Throw New ArgumentNullException("title cannot be a null reference (Nothing in Visual Basic)", "title")
        End If
        _Title = title
    End Sub

    Public ReadOnly Property Title()
        Get
            Return _Title
        End Get
    End Property

End Class

Следующий код устраняет предыдущее нарушение, переключая аргументы конструктора.

public class Book
{
    public Book(string title)
    {
        Title = title ??
            throw new ArgumentNullException(nameof(title), "All books must have a title.");
    }

    public string Title { get; }
}
Public Class Book

    Private ReadOnly _Title As String

    Public Sub New(ByVal title As String)
        If (title Is Nothing) Then
            Throw New ArgumentNullException("title", "title cannot be a null reference (Nothing in Visual Basic)")
        End If

        _Title = title
    End Sub

    Public ReadOnly Property Title()
        Get
            Return _Title
        End Get
    End Property

End Class

В следующем коде показан метод, который неправильно вызывает ArgumentNullException, где paramName не соответствует ни одному из параметров метода. Правило запускается, так как description это локальная переменная, а не параметр метода.

public class Product
{
    public string? Description { get; set; }
    public string Name { get; set; } = string.Empty;
}

public class Example
{
    // Violates CA2208: 'description' is not a parameter of this method.
    public void ProcessProduct(Product product)
    {
        string? description = product.Description;
        if (description is null)
        {
            throw new ArgumentNullException(nameof(description), $"Product named {product.Name} had no description!");
        }
        // Process description...
    }
}
Public Class Product
    Public Property Description As String
    Public Property Name As String = String.Empty
End Class

Public Class Example
    ' Violates CA2208: 'description' is not a parameter of this method.
    Public Sub ProcessProduct(ByVal product As Product)
        Dim description As String = product.Description
        If description Is Nothing Then
            Throw New ArgumentNullException(NameOf(description), $"Product named {product.Name} had no description!")
        End If
        ' Process description...
    End Sub
End Class

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

public class Product
{
    public string? Description { get; set; }
    public string Name { get; set; } = string.Empty;
}

public class Example
{
    // Fixed: Use InvalidOperationException for invalid object state.
    public void ProcessProduct(Product product)
    {
        string? description = product.Description;
        if (description is null)
        {
            throw new InvalidOperationException($"Product named {product.Name} had no description!");
        }
        // Process description...
    }
}
Public Class Product
    Public Property Description As String
    Public Property Name As String = String.Empty
End Class

Public Class Example
    ' Fixed: Use InvalidOperationException for invalid object state.
    Public Sub ProcessProduct(ByVal product As Product)
        Dim description As String = product.Description
        If description Is Nothing Then
            Throw New InvalidOperationException($"Product named {product.Name} had no description!")
        End If
        ' Process description...
    End Sub
End Class