【问题标题】:How do you maintain code with InvalidEnumArgumentException?如何使用 InvalidEnumArgumentException 维护代码?
【发布时间】:2011-07-01 09:49:55
【问题描述】:

我很好奇,一旦您抛出 System.ComponentModel.InvalidEnumArgumentException,您将如何维护您的代码。

基本上我有一个这样的 switch 语句:

switch (enumValue)
{
    case MyEnum.Value1:
        break;

    case MyEnum.Value2:
        break;

    default:
        throw new InvalidEnumArgumentException();
}

如果我决定将来为MyEnum 添加更多值,例如Value3Value4,该怎么办?这意味着我最终会抛出一个误导性的异常。我将如何防止这种情况发生?

我应该在投掷前使用反射吗?在这种情况下我应该抛出什么异常?我正在寻找建议。


几分钟前我刚刚发现了这个异常,所以我可能是在错误的上下文中查看这个异常。不支持某个枚举参数时是否会抛出此异常(在这种情况下,将不支持 Value3Value4)?

【问题讨论】:

    标签: c# maintainability


    【解决方案1】:

    您陈述的问题取决于上下文,如果方法接收枚举作为参数,它必须指定它支持哪些值以及它对未知枚举值的作用。

    如果您添加更多枚举选项,即使您在默认情况下没有抛出异常,您也需要决定要做什么。

    请注意,该异常特别有用,因为您可以将任何整数作为枚举值传递。

    例如:

    enum Foo { A, B }
    
    static int Bar(Foo f)
    {
        switch (f)
        {
            case Foo.A:
                return 1;
            case Foo.B:
                return 2;
            default:
                throw new InvalidEnumArgumentException("f", (int)f, typeof(Foo));
        }
    }
    
    static void Main()
    {
        Bar(Foo.A);
        Bar((Foo)99);
    }
    

    【讨论】:

    • 如果您只针对 dot net 4.6 或更高版本,对示例的轻微改进是将 "f" 字符串替换为 nameof(f)
    【解决方案2】:

    如果我决定将来向 MyEnum 添加更多值,例如 Value3 和 Value4,该怎么办? 这意味着我最终会抛出一个误导性的异常。我将如何防止这种情况发生?

    当您使用InvalidEnumArgumentException 时,要理解的关键是参数。通过抛出异常,您是在说该方法的 argument 无效。 (InvalidEnumArgumentException 派生自 ArgumentException。)这并不一定意味着该值不是 enum 的成员。所以我不会认为它具有误导性。

    【讨论】:

      【解决方案3】:

      我不会使用您在该上下文中使用的异常。由于 enumValue 是 MyEnum 类型(我猜?),它永远不能包含无效的枚举值。如果您有基于枚举值的开关,如果它们无法识别该值则需要失败,那么您需要抛出一个适当的异常(可能只是一个普通的 ArgumentException?)但在大多数情况下,我猜你会让代码对未知的枚举值不执行任何操作。

      【讨论】:

      • 这是不正确的。根据this addition to the design guidelines,“将任何整数值转换为枚举是合法的,即使该值未在枚举中定义。”。
      • 当然enum 值可能无效。您可以将不是枚举值之一的数字强制转换为 enum 类型。或者这可能是由于在使用扩展枚举更新的不同程序集中定义了一个枚举。
      • 我从来没有。看来我今天学到了新东西。 :-)
      【解决方案4】:

      您以错误的方式使用异常:

      http://msdn.microsoft.com/en-us/library/system.componentmodel.invalidenumargumentexception.aspx

      如果您将无效的枚举值传递给方法或设置属性时,将引发此异常。

      【讨论】:

      • 那么应该抛出什么异常呢?
      • 我只会使用 NotImplementedException - 因为我实际上没有实现代码来正确处理新添加的枚举值。
      【解决方案5】:

      我相信您在错误的上下文中查看它,如果这些不是枚举而是一些基于某些业务规则的特定值,那么在规则增加的情况下,您会修改这些相关代码以合并新的。因此,如果您正在修改 Enum,那么您应该四处寻找类似的更改。

      【讨论】:

      • 如果有很多地方都有这样的 switch 语句作用于同一个枚举,则可以拥有一个基于枚举值创建多态对象的工厂,并将该功能从开关移动到该对象的方法跨度>
      【解决方案6】:

      要验证传入的枚举值,请使用以下静态方法...

      public void MyMethod(MyEnum e)
      {
          if (!Enum.IsDefined(typeof(MyEnum), e))
              throw new InvalidEnumArgumentException("e", (int)e, typeof(MyEnum));
      

      ...如果将来添加新的枚举值,您无需更改检查。

      【讨论】:

      • 如果 MyEnum 使用新值扩展,!Enum.IsDefined(typeof(MyEnum), e)) 将为它们返回 true,因此此测试很可能永远不会失败。
      • @Spook 但如果 MyEnum 没有为 0 定义条目并且 e 在 MyEnum e; MyMethod(e); 中被隐式分配默认值或代码以数字方式设置 e 的值时,它将失败。关键是 C# 本身不会强制 e 成为 MyEnum 的有效值,而且简单地说,你不能假设任何事情。
      猜你喜欢
      • 2010-11-21
      • 1970-01-01
      • 2010-09-17
      • 2013-10-17
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 2016-06-11
      相关资源
      最近更新 更多