使用类字段作为参数时抛出 ArgumentOutOfRangeException 时的 CA2208

ama*_*ha4 4 .net c# code-analysis

验证正确的枚举值时,我抛出 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");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我在构建时遇到 CA2208 错误:

CA2208 方法“MyCLass.MyString.get()”将“_myEnum”作为“paramName”参数传递给“ArgumentOutOfRangeException”构造函数。将此参数替换为方法的参数名称之一。请注意,提供的参数名称应具有与方法上声明的完全相同的大小写。

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

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

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

O. *_*per 6

我不确定为什么这条规则如此严格,因为参数必须是方法的参数之一

这是因为您传入的任何内容都将发布在异常的ParamName属性中,该属性定义为

获取导致此异常的参数名称。

现在,如果其中没有参数名称,那么处理异常的人都会感到困惑。在某些情况下,ArgumentException甚至ParamName可能通过反射的方式求值,如果找不到参数名称,则反射可能会失败。

如果您确实想向 提供自定义消息ArgumentException,则可以使用接受自定义消息和异常(并传递null异常)的构造函数。

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

当方法调用对于对象的当前状态无效时引发的异常。

(请注意,您的代码位于属性的 getter 中,算作“方法调用”。)


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