CA2208: Instantiate argument exceptions correctly

Value
Rule ID CA2208
Category Usage
Fix is breaking or non-breaking Non-breaking

Cause

When a method has a parameter, and it throws an exception type that is, or derives from, ArgumentException, it is expected to call a constructor accepting a paramName parameter correctly. Possible causes include the following situations:

  • A call is made to the default (parameterless) constructor of an exception type that is, or derives from, ArgumentException that has a constructor accepting a paramName parameter.

  • An incorrect string argument is passed to a parameterized constructor of an exception type that is, or derives from, ArgumentException.

  • One of the parameters' names is passed for the message argument of the constructor of exception type that is, or derives from, ArgumentException.

Rule description

Instead of calling the default constructor, call one of the constructor overloads that allows a more meaningful exception message to be provided. The exception message should target the developer and clearly explain the error condition and how to correct or avoid the exception.

The signatures of the one and two string constructors of ArgumentException and its derived types are not consistent with respect to the position message and paramName parameters. Make sure these constructors are called with the correct string arguments. The signatures are as follows:

How to fix violations

To fix a violation of this rule, call a constructor that takes a message, a parameter name, or both, and make sure the arguments are proper for the type of ArgumentException being called.

Tip

A code fix is available in Visual Studio for incorrectly positioned parameter names. To use it, position the cursor on the warning row and press Ctrl+. (period). Choose Swap the arguments order from the list of options that's presented.

Code fix for CA2208 - swap arguments.

If a parameter name instead of a message is passed to the ArgumentException(String) method, the fixer provides the option to switch to the two-argument constructor instead.

Code fix for CA2208 - switch to two-argument constructor.

When to suppress warnings

It's safe to suppress a warning from this rule only if a parameterized constructor is called with the correct string arguments.

Suppress a warning

If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.

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

To disable the rule for a file, folder, or project, set its severity to none in the configuration file.

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

To disable this entire category of rules, set the severity for the category to none in the configuration file.

[*.{cs,vb}]
dotnet_analyzer_diagnostic.category-Usage.severity = none

For more information, see How to suppress code analysis warnings.

Configure code to analyze

Use the following option to configure which parts of your codebase to run this rule on.

You can configure this option for just this rule, for all rules, or for all rules in this category (Design). For more information, see Code quality rule configuration options.

Include specific API surfaces

You can configure which parts of your codebase to run this rule on, based on their accessibility. For example, to specify that the rule should run only against the non-public API surface, add the following key-value pair to an .editorconfig file in your project:

dotnet_code_quality.CAXXXX.api_surface = private, internal

By default, the CA2208 rule applies to all API surfaces (public, internal, and private).

Example

The following code shows a constructor that incorrectly instantiates an instance of 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

The following code fixes the previous violation by switching the constructor arguments.

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