【问题标题】:Why operators << and >> are not realized for flag enums in C#?为什么 C# 中的标志枚举没有实现运算符 << 和 >>?
【发布时间】:2011-10-17 10:19:15
【问题描述】:

我想做这样的事情,但我做不到:

[Flags]
enum SomeEnum : int
{ 
 None = 0,
 A,
 B,
 C
}

SomeEnum en = SomeEnum.A;
en <<= 1; //Expect en == SomeEnum.B but I recieve an error here

为了什么?

【问题讨论】:

  • 可能是因为这增加了编译器的复杂性,但在考虑测试、文档等时几乎没有什么好处。
  • 这看起来会让事情变得更难阅读。你能举个例子说明你什么时候想做这样的事情吗?
  • 您可以在执行任何永远不会在枚举上使用的逻辑之前将枚举转换为 int,因为枚举根本不适合。无论如何:en = (SomeEnum)((int)en
  • 不允许这样做的一个原因是移位操作理论上可能会生成一个对枚举无效的值。除了

标签: c# .net enums enum-flags


【解决方案1】:

枚举本身不是位域。枚举的全部意义在于抽象出任何基础值。使用移位运算符意味着知道这些值是什么。

不过,如果你真的想换档,那就投吧:

en = (SomeEnum)((int)en << 1);

【讨论】:

    【解决方案2】:

    [Flag] 枚举可以包含标志的组合。改变组合很少会产生有意义的意义

    SomeEnum en = SomeEnum.A | SomeEnum.B;
    en <<= 1; //Expect what?
    

    你可以转换为 int,如果你知道你在做什么,你可以做你喜欢的事

    注意:如果你真的想使用 SomeEnum 而不显式转换,你可以用我在此处定义的 Pseudo&lt;SomeEnum&gt; 之类的类型包装它:Is it possible to wrap integer and call it like integer?

    请注意,这实际上是一个概念证明,但您可以从那里看到它是如何工作的

    【讨论】:

    • 添加了关于用类型帽子包装枚举的信息,它会进行隐式转换以避免强制转换
    • 技术上他会期望SomeEnum.B | SomeEnum.C
    • @JonathanDickinson:问题是,(a)我们不知道他的期望(b)这可能是编译器不支持它的一个很好的理由
    • 同意,但是,从知道自己想要什么的人的角度来看(例如,作为一个糟糕的例子,也许它是一个权限枚举,其中增加的值通常代表增加的状态)。你可以用位域数学做一些疯狂的聪明的事情——你永远不知道;知道他们期望什么的人可能会来阅读您的答案。
    • @JonathanDickinson:我认为你举了一个糟糕的例子。该示例适用于 int 和简单的增量。 特别是对于权限映射,您不希望整数移位语义(您希望获得更多权限 (OR),或“执行”权限保持不变,同时增加一些其他权限...... )
    【解决方案3】:

    我会说这是因为您“不能将运算符'

    var en = SomeEnum.A;
    
    en = (SomeEnum)((int)en << 1);
    

    哪个显式进行类型转换,或者,如果您愿意,您可以等待 &lt;&lt;= 被实现或 Enum 隐式转换为 int 运算符来实现,这两者似乎都不太可能,它不应该是偶然发生的。

    您可以编写自己的扩展方法来实现相同的目的,但我认为这需要使用一些反射来处理 Enum 的不同基本类型

    【讨论】:

      猜你喜欢
      • 2016-06-30
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 2013-10-27
      • 2010-10-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多