【问题标题】:Why enums require an explicit cast to int type?为什么枚举需要显式转换为 int 类型?
【发布时间】:2011-01-18 19:43:41
【问题描述】:

这样做不会丢失数据,那么必须将枚举显式转换为整数的原因是什么?

如果它是隐式的,会不会更直观,比如当你有更高级别的方法时:

PerformOperation ( OperationType.Silent type )

PerformOperation 调用封装的 C++ 方法,该方法暴露如下:

_unmanaged_perform_operation ( int operation_type )

【问题讨论】:

    标签: c# .net enums casting


    【解决方案1】:

    枚举有两种主要且不一致的用法:

    enum Medals
    { Gold, Silver, Bronze }
    
    [Flags]
    enum FilePermissionFlags
    {
        CanRead = 0x01,
        CanWrite = 0x02,
        CanDelete = 0x04
    }
    

    在第一种情况下,将这些东西视为数字是没有意义的。它们存储为整数的事实是一个实现细节。您不能在逻辑上加、减、乘或除金、银和铜。

    在第二种情况下,将这些东西视为数字是没有意义的。你不能加、减、乘或除它们。唯一合理的操作是按位操作。

    枚举是糟糕的数字,所以你不应该把它们当作数字来处理。

    【讨论】:

    • 当显式指定枚举时,如何将枚举隐式转换为其基础值类型。即“enum FilePermissionFlags : int”可以隐式转换为 int。
    • @Lazlo:当枚举从元数据中加载时,您如何判断源代码中的内容?开启行为是一件非常奇怪的事情。在我看来,真正更好的是真正的枚举类型,比如“奖牌”,它不能转换为任何类型的整数,以及一种特殊的整数,它是一个“标志 uint”,它具有按位运算. int 被混为小数 小位数组的事实似乎很正常,因为我们是伴随着它长大的。事实上,这真的很恶心。
    • @Eric:正如你所说,枚举确实很糟糕(IsDefined hack 是另一个例子)。它们似乎被视为一个特殊的概念,但在编译器中没有必要的基础设施来让它们表现得合理。
    • @nicodemus13:我完全同意。我希望我们制作了两种枚举:标志集合和不同的值。
    • @Eric Lippert:嗯,下一次!用一门好语言表达的小烦恼。
    【解决方案2】:

    因为枚举不必基于int

    枚举关键字用于声明一个 枚举,一种独特的类型 由一组命名常量组成 称为枚举数列表。每一个 枚举类型有一个底层 类型,可以是任何整数类型 字符除外。

    所以你可以这样做:

    enum Something :long  { valueX = 0, valueY = 2147483648L }
    

    【讨论】:

    • 你是对的,但是编译器可以确定枚举是否基于 int 并允许这样做,或者通过其他方式强制执行基于 int 的枚举?
    • 或者,它可以尝试始终隐式转换为第一个成员的类型。
    • 当然编译器可以 - 但是valueY - valueX 的含义是什么?如果名称是BlueCheckered 怎么办?如果您经常将枚举用作整数,以至于显式转换是一种负担,那么也许您应该质疑您的设计。
    • 我只是想找出我现在得到的原因。但我不认为我的设计有什么问题,因为就像我说的包装框架超出了我的控制范围。
    【解决方案3】:

    为什么说没有数据丢失?毕竟,并非所有枚举都是整数。它们必须是整数类型,但可以表示字节、ulong 等。

    作为极端情况,文字 0 隐含的,但是;你在这里的用例是什么?

    我很少需要这样做 - 通常是数据导入等。偶尔的空投对我来说非常有意义,并且可以避免意外错误。

    【讨论】:

    • 谢谢,我不确定你在第二段中的意思。 0 可以隐式转换为枚举?
    • @Joan:规范说任何 literal zero 都可以转换为任何枚举,因此即使有枚举中没有定义零值。编译器实际上允许任何常量零。有关可怕的细节,请参阅 blogs.msdn.com/b/ericlippert/archive/2006/03/28/563282.aspxblogs.msdn.com/b/ericlippert/archive/2006/03/29/…
    • @Eric:谢谢,我现在明白了。我也不清楚马克的第一段。所以枚举是基于 int 的,成员是字符串还是其他类型?就像成员存储为整数一样?
    • @Joan - 考虑 enum Foo : sbyte {..} - 这里的每个成员都是 sbyte,而不是 int。
    【解决方案4】:

    如果它是隐式的,会不会更直观,比如当你有更高级别的方法时:

    其实我不这么认为。在这种情况下,您尝试在边缘情况下使用 Enum。

    但是,如果枚举被隐式转换为整数值,这将大大降低其有效性。通过显式地强制进行 int 转换,编译器将 enum 视为一种特殊类型 - 许多选项之一,而不是整数。这更清楚地展示了枚举的意图,并减少了程序员出错的机会(即:将未在枚举中定义的值分配给枚举变量等)。

    我个人很高兴 C# 中的枚举不仅仅是(实际上)一个常量 int 值。

    【讨论】:

      【解决方案5】:

      我认为“为什么枚举需要显式转换为 int 类型?”的答案。是不是 C# 中的强类型枚举是防止常见编程错误的有用防御措施。

      假设我有一个基于两个枚举的绘画管理应用程序:

      enum Textures { Gloss, Satin, Matt };
      enum Colors { White, Green, Red, Blue, Brown };
      

      还有一个像这样的房间绘画方法:

      private void PaintRoom (Textures texture, Colors color)
      

      在像 C# 这样具有强枚举类型的语言中,这样的命令:

       // nonsensical attempt to have texture=White and color=Matt
      PaintRoom(Colors.White, Textures.Matt);
      

      ...会产生编译时错误(无法将颜色放入预期纹理的位置,反之亦然)。但是在枚举不是强类型和/或可能发生隐式转换的语言中(包括 C 和 C++),我们的Colors 和我们的Textures 都可以被视为int,所以我们可以愉快地发出PaintRoom(Colors.White, Textures.Matt) 命令,它会编译得很好,但我们最终得到了一个漆成光泽红 (0, 2) 的房间,而不是我们想要的哑光白 (2, 0),并且快速浏览的代码似乎在说。

      因此,强类型枚举主要是一件好事,可以防止人们不小心将枚举放入不适合的地方。如果有人真的希望他们的枚举是int,C# 会强制编码人员通过坚持显式转换来明确他们的意图。

      【讨论】:

        【解决方案6】:

        这就是 C# 的工作方式......

        如果 Enum 继承自 int,那么这应该是可能的。 Enum 不继承自 int,因此需要强制转换。

        隐式转换类的唯一方法是它们是否继承。

        【讨论】:

          【解决方案7】:

          正如其他人所说,将所需的演员表从EnumType 更改为int 是不可能的。但是,有几种解决方法。例如,我有几个引用类似事物的枚举,并且希望能够将它们中的任何一个分配给一个变量。所以我选择了:

          public ValueType State {
              get {
                  return state;
              }
              set {
                  state = (int)value;
              }
          }
          

          因此,我可以同时说 playerObject.animator.State = Player.STANDINGmonsterObject.animator.State = Monster.DROOLING,就调用类可以说的而言。

          另外,是的,我必须将枚举值视为数字是有正当理由的。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-08-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-22
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多