【问题标题】:Casting an out-of-range number to an enum in C# does not produce an exception在 C# 中将超出范围的数字转换为枚举不会产生异常
【发布时间】:2009-03-06 10:06:04
【问题描述】:

以下代码不会产生异常,而是将值 4 传递给 tst。谁能解释这背后的原因?

 public enum testing
 { 
    a = 1,
    b = 2,
    c = 3
 }

testing tst = (testing)(4);

【问题讨论】:

    标签: c# exception enums casting


    【解决方案1】:

    在 C# 中,与 Java 不同,枚举不被检查。您可以具有基础类型的任何值。这就是为什么检查您的输入非常重要的原因。

    if(!Enum.IsDefined(typeof(MyEnum), value))
         throw new ArgumentOutOfRangeException();
    

    【讨论】:

    • 作为 Java 开发人员(LINQ!),我渴望 C# 的一些特性,但这里 Java 确实做到了......
    • @saua:不一定。它们是这种方法的优点,也是缺点。
    • 这一点的主要优点是可以组合值,还应该用[Flags]属性标记。
    • 我知道,但我也可以使用 EnumSet 来做到这一点,在我看来,它不像位摆弄那样多,而且 OO 更多。一般来说,我更喜欢Java方式,其中枚举是伪装的对象,而不是伪装的整数。但这当然是相当主观的。
    • saua:一般来说,Java 的枚举要强大得多。但在这个简单的例子中,.NET 推理是无可挑剔的:对潜在无效标志组合的运行时检查是耗时的,并且在大多数情况下完全没用:你会为一个你不使用的功能付出很多,除非很少使用。跨度>
    【解决方案2】:

    由于您的枚举是基于 int 的,它可以接受 int 可以接受的任何值。并且由于您明确地(通过强制转换)告诉编译器可以将 4 强制转换到您的枚举中。

    【讨论】:

      【解决方案3】:

      每个枚举都有一个用于表示的底层数字类型(例如 int)。即使一个值没有名称,它也是枚举可以具有的可能值。

      【讨论】:

        【解决方案4】:

        其他人没有说的:通过强制转换,您告诉编译器您知道自己在做什么。所以如果你告诉它,把它当作一个枚举值,它确实如此。其他发帖者指出了为什么仍然允许这样做,因为 C# 编译器不允许很多坏事,即使你说你知道自己在做什么。

        如果该值不被允许,那就太糟糕了,因为那样你就不能将标志值保存为 int。或者,有人必须检查 int 是否是允许的组合之一,如果您使用标志枚举(值可以一起进行或运算),这可能会很多。

        【讨论】:

        • 我不确定第二段是否真的适用。该评论是关于该语言是否应允许演员表,但问题是演员表做什么,是否应该检查。 C# 已选择允许 enum 类型的变量能够保存基础整数类型具有的任何值。如果值在枚举中不可表示,另一种方法是检查并抛出 InvalidCastException
        • Enum.ParseEnum.TryParse 方法也会发生这种情况,因此这里的问题与强制转换无关,而是与语言决定有关。
        猜你喜欢
        • 2017-04-21
        • 2023-03-05
        • 1970-01-01
        • 2014-03-06
        • 2018-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多