Search code examples
c#.netcode-analysis

CA2208 when throwing ArgumentOutOfRangeException when using class field as argument


I'm throwing an ArgumentOutOfRangeException when validating correct enum values:

internal class MyClass : IMyInterface
{
    private readonly MyEnum _myEnum;

    public MyClass(MyEnum myEnum) => _myEnum = myEnum;

    public String MyString
    {
        get
        {
            switch (_myEnum)
            {
                case MyEnum.A:
                    return "A";
                case MyEnum.B:
                    return "B";
                default:
                    throw new ArgumentOutOfRangeException("_myEnum");
            }
        }
    }
}

I'm getting a CA2208 error when building:

CA2208 Method 'MyCLass.MyString.get()' passes '_myEnum' as the 'paramName' argument to a 'ArgumentOutOfRangeException' constructor. Replace this argument with one of the method's parameter names. Note that the provided parameter name should have the exact casing as declared on the method.

I'm not sure why this rule is so restrictive in that the argument has to be one of the method's parameters, and I can't use the class field.

I'm considering suppressing this warning, but I'd rather investigate why this is being called out.

Note: The MyString property is part of IMyInterface and cannot take this enum value as an argument.


Solution

  • I'm not sure why this rule is so restrictive in that the argument has to be one of the method's parameters

    That's because whatever you pass in there will be published in the ParamName property of the exception, which is defined as

    Gets the name of the parameter that causes this exception.

    Now, if whatever is in there is not a parameter name, things can get confusing for whoever processes the exception. In a few cases, the ArgumentException and its ParamName might even be evaluated by means of reflection, which could fail if the parameter name is not found.

    If you really want to supply a custom message to ArgumentException, you can use the constructor that accepts a custom message and an exception (and pass null for the exception).

    However, as your exception does not indicate an invalid argument, I'd argue ArgumentException is not the right exception to use. You throw an exception because a property of your object has an invalid value - that is, because your object is in an invalid state. The correct exception to throw in this case is InvalidOperationException, which is defined as

    The exception that is thrown when a method call is invalid for the object's current state.

    (Note that your code being in the getter of a property counts as a "method call".)


    As an aside, even if enum value were an argument, ArgumentException may not be the most appropriate choice. There is InvalidEnumArgumentException, which is specifically meant for use with enum values.