CA2208: Správně vytvářejte výjimky týkající se argumentů

Vlastnost Hodnota
ID pravidla CA2208
Název Správně instancujte výjimky argumentu
Kategorie Využití
Oprava, která může být destruktivní nebo nedestruktivní Nezlomitelný
Povoleno ve výchozím nastavení v .NET 10 Jako návrh
Příslušné jazyky C# a Visual Basic

Příčina

Když má metoda parametr a vyvolá typ výjimky, který je nebo je odvozen od ArgumentException, je očekáváno správné volání konstruktoru, který přijímá parametr paramName. Mezi možné příčiny patří následující situace:

  • Volání výchozího (bezparametrového) konstruktoru výjimky, která je typu ArgumentException nebo z něj odvozena a má také konstruktor, který přijímá parametr paramName.
  • Nesprávný argument řetězce je předán parametrizovanému konstruktoru výjimky typu, který je nebo je odvozen od ArgumentException. paramName Argument například neodpovídá názvu jednoho z parametrů metody.
  • Název parametru message je předán pro argument konstruktoru typu výjimky, který je nebo odvozen od, ArgumentException.

Popis pravidla

Místo volání výchozího konstruktoru zavolejte některé z přetížení konstruktoru, které umožňuje poskytnout výstižnější zprávu o výjimce. Zpráva o výjimce by měla cílit na vývojáře a jasně vysvětlit chybovou podmínku a způsob opravy nebo zabránění výjimce.

Podpisy jednoho a dvou řetězcových konstruktorů ArgumentException a těchto odvozených typů nejsou konzistentní s ohledem na pozice parametrů message a paramName. Ujistěte se, že tyto konstruktory jsou volány se správnými řetězcovými argumenty. Podpisy jsou následující:

Jak opravit porušení

Chcete-li opravit porušení tohoto pravidla, zavolejte konstruktor, který přebírá zprávu, název parametru nebo obojí, a ujistěte se, že argumenty jsou správné pro typ ArgumentException volání.

Tip

Oprava kódu je k dispozici v sadě Visual Studio pro nesprávně umístěné názvy parametrů. Pokud ho chcete použít, umístěte kurzor na řádek upozornění a stiskněte Ctrl+. V zobrazeném seznamu možností zvolte Prohodit pořadí argumentů.

Oprava kódu pro CA2208 – výměna argumentů

Pokud je metodě předán ArgumentException(String) název parametru místo zprávy, fixer místo toho poskytuje možnost přepnout na konstruktor se dvěma argumenty.

Oprava kódu pro CA2208 – přepněte na konstruktor se dvěma argumenty.

Kdy potlačit upozornění

Upozornění z tohoto pravidla je bezpečné potlačit pouze v případě, že je parametrizovaný konstruktor volán se správnými řetězcovými argumenty.

Potlačení upozornění

Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.

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

Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none konfiguračním souboru.

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

Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.

Konfigurace kódu pro analýzu

Pomocí následující možnosti nakonfigurujte, ve kterých částech základu kódu se má toto pravidlo spouštět.

Tuto možnost můžete nakonfigurovat jenom pro toto pravidlo, pro všechna pravidla, která platí, nebo pro všechna pravidla v této kategorii (Návrh), na která platí. Další informace naleznete v tématu Možnosti konfigurace pravidla kvality kódu.

Zahrnutí konkrétních povrchů rozhraní API

Nastavením možnosti api_surface můžete nakonfigurovat, na kterých částech základu kódu se má toto pravidlo spouštět na základě jejich přístupnosti. Pokud chcete například určit, že pravidlo by se mělo spouštět jenom na neveřejné ploše rozhraní API, přidejte do souboru .editorconfig v projektu následující pár klíč-hodnota:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Poznámka

Nahraďte XXXX část CAXXXX ID příslušného pravidla.

Ve výchozím nastavení se pravidlo CA2208 vztahuje na všechny plochy rozhraní API (veřejné, interní a soukromé).

Příklad

Následující kód ukazuje konstruktor, který nesprávně vytvoří instanci 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

Následující kód opravuje předchozí porušení přepnutím argumentů konstruktoru.

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

Následující kód ukazuje metodu, která nesprávně vyvolá ArgumentNullException s paramName, který neodpovídá žádnému z parametrů metody. Pravidlo se aktivuje, protože description je místní proměnná, nikoli parametr metody.

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

Následující kód opravuje předchozí porušení tím, že místo toho použije InvalidOperationException, což je vhodné, když je stav objektu neplatný.

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