Search code examples
c#upgrade.net-6.0

.NET 6 replace parameter checks with ArgumentNullException.ThrowIfNull();


I'm upgrading our application to .NET 6 from .NET 3.1 Core and trying to use the new ArgumentNullException.ThrowIfNull();

But in our code, we do not only check for null but also for other things.

if (anyParam == null)
{
    throw new ArgumentNullException(nameof(anyParam));
}

if (string.IsNullOrEmpty(stringParam))
{
    throw new ArgumentException(nameof(stringParam));
}

if (intParam <= 0)
{
    throw new ArgumentException(nameof(intParam ));
}

if (listParam.Count == 0)
{
    throw new ArgumentException(nameof(listParam));
}

Since Rule CA2208 now wants to change all ArgumentException lines, which we have a lot of, this would be a lot of work.

I want to know is it only safe to replace pure null checks like in the first example, or what is it all checking for in case of different parameter types. Couldn't find the proper documentation.

I would like to replace as much as I can with:

ArgumentNullException.ThrowIfNull(anyParam);

Solution

  • You are mixing up two completely unrelated issues here:

    The first one is replacing your very first check with ArgumentNullException.ThrowIfNull. Sure, that's a good idea to do! Starting with .NET 7, you will also be able to replace your second check with ArgumentException.ThrowIfNullOrEmpty.

    The second issue is that your second, third and fourth checks are broken and should be fixed (this is what CA2208 is about): The first parameter of ArgumentNullException is paramName, but the first parameter of ArgumentException is not paramName, it's message.

    For example, your line

    if (intParam <= 0)
    {
        throw new ArgumentException(nameof(intParam));
    }
    

    should actually be:

    if (intParam <= 0)
    {
        throw new ArgumentException(nameof(intParam) + " must be a positive integer.");
    }
    

    (Or, optionally:)

    if (intParam <= 0)
    {
        throw new ArgumentException(nameof(intParam) + " must be a positive integer.", 
                                    nameof(intParam));
    }
    

    As suggested in the comments, ArgumentOutOfRangeException might be an even better option for this particular check. Note though, that, contrary to ArgumentException's constructor, ArgumentOutOfRangeException (like ArgumentNullException) takes the parameter name first and then (optionally) the message. I.e., you can use either

    if (intParam <= 0)
    {
        // yield a generic "out of range" exception message
        throw new ArgumentOutOfRangeException(nameof(intParam));
    }
    

    or

    if (intParam <= 0)
    {
        throw new ArgumentOutOfRangeException(nameof(intParam),
            nameof(intParam) + " must be a positive integer.");
    }