使用 class 字段作为参数时抛出 ArgumentOutOfRangeException 时出现 CA2208

CA2208 when throwing ArgumentOutOfRangeException when using class field as argument

我在验证正确的枚举值时抛出 ArgumentOutOfRangeException:

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");
            }
        }
    }
}

我在构建时遇到 CA2208 错误:

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.

我不确定为什么这条规则如此严格,因为参数必须是方法的参数之一,而且我不能使用 class 字段。

我正在考虑取消此警告,但我宁愿调查为什么会发出此警告。

注意:MyString 属性 是 IMyInterface 的一部分,不能将此枚举值作为参数。

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

那是因为你传入的任何内容都会在异常的ParamName property中发布,定义为

Gets the name of the parameter that causes this exception.

现在,如果其中的内容 不是 参数名称,那么处理异常的人可能会感到困惑。在少数情况下,ArgumentException 及其 ParamName 甚至可能通过反射进行计算,如果未找到参数名称,则可能会失败。

如果您真的想向 ArgumentException 提供自定义消息,您可以使用 constructor that accepts a custom message and an exception(并传递 null 作为例外)。

但是,因为你的例外并不表示无效的参数,我认为ArgumentException是不正确的使用异常。您抛出异常是因为您的对象的 属性 具有无效值 - 也就是说,因为您的对象处于无效状态。在这种情况下抛出的正确异常是 InvalidOperationException,定义为

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

(请注意,您的代码在 属性 的 getter 中算作 "method call"。)


顺便说一句,即使枚举值是一个参数,ArgumentException 也可能不是最合适的选择。有 InvalidEnumArgumentException,专门用于枚举值。