C# 是否有其他方法来测试枚举位字段?

C# 是否有其他方法来测试枚举位字段?,c#,enums,bit-manipulation,C#,Enums,Bit Manipulation,将枚举与位字段一起使用时: enum ReallyBigEnum { FirstChoice = 0x01, AnotherOption = 0x02 } ReallyBigEnum flag = ReallyBigEnum.FirstChoice | ReallyBigEnum.AnotherOption; 用于测试位的代码为: if( (flag & ReallyBigEnum.AnotherOption) == ReallyBigEnum.AnotherO

将枚举与位字段一起使用时:

   enum  ReallyBigEnum  { FirstChoice = 0x01, AnotherOption = 0x02 }
   ReallyBigEnum  flag = ReallyBigEnum.FirstChoice | ReallyBigEnum.AnotherOption;
用于测试位的代码为:

   if( (flag & ReallyBigEnum.AnotherOption) == ReallyBigEnum.AnotherOption ) { ... }
由于需要重复该位,因此看起来冗长且容易出错 正在测试中

如果有什么方法可以说:

   if( flag.IsSet( ReallyBigEnum.AnotherOption ) ) { ... }
但是枚举不支持实例方法。因此,我尝试了一个模板函数:

   class Enums
   {
      public static bool IsSet<T>( T flag, T bit ) { return (flag & bit) == bit; }
   }
但是,您必须将每个值强制转换为其基本类型,如下所示:

   if( Enums.IsSet<ReallyBigEnum>( flag, ReallyBigEnum.AnotherOption ) ) { ... }
   if( Enums.IsSet( (int)flag, (int)ReallyBigEnum.AnotherOption ) ) { ... }
这也是一个痛苦的代码,并失去了类型检查的好处

可以编写相同的函数来使用“对象”参数,但是 必须测试对象类型和基础基类型

所以,我坚持用标准的,多余的方式在顶部

有没有人对测试枚举位字段的干净、简单的方法有其他想法


非常感谢。

到.Net 3.5这是您唯一的选择。在.NET4.0中,枚举上有一个
HasFlag
方法

if((flag & ReallyBigEnum.AnotherOption) != 0) { ... }
更新:

显然,只有在测试单个位时,上述方法才有效。如果要测试多个位,则需要其他内容,这取决于您是检查所有位还是任何位

测试是否设置了一组位中的任何一位

对于这种情况,只需使用单位版本的变体

if((flag & (ReallyBigEnum.FirstOption | ReallyBigEnum.AnotherOption)) != 0) { ... }
测试一组位是否全部设置

对于这种情况,为了获得清晰性和可靠性,我建议创建一个包含所有位的常量

const int ReallyBigEnum WickedAwesomeOptions = ReallyBigEnum.FirstOption | ReallyBigEnum.AnotherOption;
...
if (flag & WickedAwesomeOptions == WickedAwesomeOptions) { ... }
一些冗余仍然存在,但它并不脆弱或混乱,并且易于维护

如果位组合应用广泛,则可以将其添加到枚举本身

[Flags]
enum ReallyBigEnum
{
    FirstOption = 1,
    AnotherOption = 2,
    WickedAwesomeOptions = FirstOption | AnotherOption,
}
....
if (flag & ReallyBigEnum.WickedAwesomeOptions == ReallyBigEnum.WickedAwesomeOptions) { ... }

当然,HasFlag()方法是完美的解决方案。谢谢不幸的是,我们的开发环境仍然使用.NET2.0。这是一个非常好的解决方案。文档表明,对于C#,扩展方法与原始类方法一样有效。在.NETV3.0中引入了扩展方法。此代码假设枚举的大小也可以基于无符号整数和长整数。如果将强制转换更改为:(long)(object)值,它是否适用于所有整数类型?这假设枚举由整数支持,这是标准兼容枚举的情况,但有更多类型。字节备份的枚举(在与本机代码的互操作中使用)将在此失败。这将删除冗余,但仅当所有标志都是单位时才起作用。带有多个位的复合标志可能返回误报。@克里斯C。-确定它只适用于单位标志。这正是问题所要求的。问题的任何部分都没有询问检查多个位。@Chris C.-我修改了答案以解决这个新问题。
[Flags]
enum ReallyBigEnum
{
    FirstOption = 1,
    AnotherOption = 2,
    WickedAwesomeOptions = FirstOption | AnotherOption,
}
....
if (flag & ReallyBigEnum.WickedAwesomeOptions == ReallyBigEnum.WickedAwesomeOptions) { ... }
/// <summary>
/// Taken from https://stackoverflow.com/questions/9033/hidden-features-of-c/407325#407325
/// instead of doing (enum & value) == value you can now use enum.Has(value)
/// </summary>
/// <typeparam name="T">Type of enum</typeparam>
/// <param name="type">The enum value you want to test</param>
/// <param name="value">Flag Enum Value you're looking for</param>
/// <returns>True if the type has value bit set</returns>
public static bool Has<T>(this System.Enum type, T value)
{
   return (((int)(object)type & (int)(object)value) == (int)(object)value);
} 
MyFlagEnum e = MyFlagEnum.First | MyFlagEnum.Second;
if(e.Has(MyFlagEnum.First))
{
   // Do stuff
}