CA2208: Instantiate argument exceptions correctly

The CA2208 code analysis rule checks for common mistakes when constructing argument exceptions. There are three main argument exception classes: ArgumentException, ArgumentNullException, and ArgumentOutOfRangeException. Unfortunately, it’s easy to make a mistake when using these. I’ll explain the common mistakes that CA2208 checks for and how to fix them (and when to suppress the warning instead).

Case 1 – paramName / message are passed in the wrong order

When you pass in the argument exception parameters in the wrong order, you’ll get a CA2208 warning such as:

CA2208 Method … passes parameter name ‘id’ as the message argument to a ArgumentOutOfRangeException constructor. Replace this argument with a descriptive message and pass the parameter name in the correct position.

Here’s an example of this problem. The order of the parameters is (paramName, message), and they are accidentally passed in as (message, paramName):

//Method signature
public ArgumentOutOfRangeException(string? paramName, string? message);

//Example of passing the parameters in the wrong order:
throw new ArgumentOutOfRangeException("Valid range: 100-999", nameof(id));
Code language: C# (cs)

Note: To make matters more confusing, ArgumentException has the opposite parameter order (message, paramName).

The simple answer here is to put the arguments in the right order. However, I’d suggest using named arguments instead. To go one step further, I’d suggest using a throw helper method (i.e. ArgumentException.ThrowIfNull) which can automatically get the argument name for you (therefore eliminating this issue to begin with).

When you have two parameters of the same type (string in this case) right next to each other, it’s very easy to accidentally transpose them as shown above. The best way to guard against this type of problem in general is to get in the habit of using named arguments (which makes the parameter order irrelevant). Here’s an example of creating an argument exception with named arguments:

throw new ArgumentOutOfRangeException(message: "Valid range: 100-999", paramName: nameof(id));
Code language: C# (cs)

Passing in just the parameter name to ArgumentException

ArgumentException doesn’t have an overload that accepts just paramName, but it does have one that accepts just message. When the compiler can tell you’re passing in a parameter name for message, it will report the same CA2208 warning as shown in the previous section. Here’s an example of what would cause this:

throw new ArgumentException(nameof(id));
Code language: C# (cs)

Is this really a problem? It’s up to you. Perhaps you really want to pass just the parameter name like this, and want to get rid of the CA2208 warning. In that case, you can suppress CA2208 for this line of code:

#pragma warning disable CA2208 // Instantiate argument exceptions correctly
 throw new ArgumentException(nameof(id));
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
Code language: C# (cs)

Case 2 – paramName doesn’t match the method’s parameters

When you pass in paramName to an argument exception, the compiler checks if it matches the name of one of the method parameters. If it doesn’t, match, you’ll get a CA2208 warning like this:

CA2208 Method … passes ‘id’ as the paramName argument to a ArgumentNullException constructor. Replace this argument with one of the method’s parameter names.

First, if you want paramName to match the method parameter name exactly, I suggest using the nameof() operator instead of hardcoding the name:

public Person Get(string uniqueId)
{
	throw new ArgumentNullException(paramName: nameof(uniqueId));
}
Code language: C# (cs)

Second, let’s say you’re intentionally using a parameter’s property name instead of the parameter’s name. Here’s an example:

public void Post(Person person)
{
	throw new ArgumentNullException(paramName: nameof(person.FirstName));
}
Code language: C# (cs)

It’s perfectly fine to throw an argument exception for a parameter’s property like this, and clearly paramName won’t match the parameter name. In this case, if you really want to get rid of the CA2208 warning, you can suppress it for this line:

#pragma warning disable CA2208 // Instantiate argument exceptions correctly
throw new ArgumentNullException(paramName: nameof(person.FirstName));
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
Code language: C# (cs)

Case 3 – Using a parameterless constructor

When you use an argument exception’s parameterless constructor (i.e. new ArgumentException()), you’ll get a CA2208 warning like this:

CA2208 Call the ArgumentException constructor that contains a message and/or paramName parameter

While using the parameterless constructor isn’t technically wrong (it exists after all), in most cases it probably makes sense to pass in message / paramName to provide specific information about the exception.

However, if you decide that it makes more sense to use the parameterless constructor, and you want to get rid of the CA2208 warning, you can suppress CA2208 for this line:

#pragma warning disable CA2208 // Instantiate argument exceptions correctly
throw new ArgumentNullException();
#pragma warning restore CA2208 // Instantiate argument exceptions correctly
Code language: C# (cs)

Leave a Comment