还有另一种方法来测试 Enum 位字段吗?

发布于 2024-09-19 06:26:47 字数 1258 浏览 5 评论 0原文

当使用带有位字段的枚举时:

   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 ) ) { ... }

需要编写很多内容。然后我尝试缩短它:

   class Enums
   {
      public static bool IsSet( int flag, int bit ) { return (flag & bit) == bit; }
   }

但是您必须将每个值转换为其基本类型,如下所示:

   if( Enums.IsSet( (int)flag, (int)ReallyBigEnum.AnotherOption ) ) { ... }

这对编码来说也是一种痛苦,并且失去了类型检查的好处。

可以编写相同的函数来使用“对象”参数,但随后 必须测试对象类型和底层基本类型。

所以,我坚持使用顶部的标准、冗余方式。

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

非常感谢。

When using Enums with bit fields:

   enum  ReallyBigEnum  { FirstChoice = 0x01, AnotherOption = 0x02 }
   ReallyBigEnum  flag = ReallyBigEnum.FirstChoice | ReallyBigEnum.AnotherOption;

the code used to test the bits is:

   if( (flag & ReallyBigEnum.AnotherOption) == ReallyBigEnum.AnotherOption ) { ... }

which seems verbose and error prone because of the need to repeat the bit
being tested.

It would be nice if there were some way to say:

   if( flag.IsSet( ReallyBigEnum.AnotherOption ) ) { ... }

but Enums don't support instance methods. So, I tried a template function:

   class Enums
   {
      public static bool IsSet<T>( T flag, T bit ) { return (flag & bit) == bit; }
   }

but the code to test bits then looks like this:

   if( Enums.IsSet<ReallyBigEnum>( flag, ReallyBigEnum.AnotherOption ) ) { ... }

which is a lot to write. Then I tried to shorten it:

   class Enums
   {
      public static bool IsSet( int flag, int bit ) { return (flag & bit) == bit; }
   }

but then you have to cast each value to its base type like this:

   if( Enums.IsSet( (int)flag, (int)ReallyBigEnum.AnotherOption ) ) { ... }

which is also a pain to code and loses the benefit of type checking.

The same function could be written to use 'object' parameters, but then
the object type and underlying base type would have to be tested.

So, I'm stuck with the standard, redundant way at the top.

Does anyone have other ideas on a clean, simple way of testing Enum bit fields?

Much Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

往事随风而去 2024-09-26 06:26:47

在 .Net 3.5 之前,这是您唯一的选择。在 .Net 4.0 中,枚举有一个 HasFlag 方法。

Up to .Net 3.5 this is your only option. In .Net 4.0 there is a HasFlag method on the enum.

他不在意 2024-09-26 06:26:47
/// <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
}
/// <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);
} 

Here is an Extension Method I took from the above link

Use:

MyFlagEnum e = MyFlagEnum.First | MyFlagEnum.Second;
if(e.Has(MyFlagEnum.First))
{
   // Do stuff
}
神仙妹妹 2024-09-26 06:26:47
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) { ... }
if((flag & ReallyBigEnum.AnotherOption) != 0) { ... }

UPDATED:

The above obviously work only if you're testing a single bit. If you want to test multiple bits, then something else is required, depending on whether you are checking for all bits or any bit.

Testing that any of a set of bits is set

For this case, just use a variant of the single bit version.

if((flag & (ReallyBigEnum.FirstOption | ReallyBigEnum.AnotherOption)) != 0) { ... }

Testing that all of a set of bits is set

For this case to achive clarity and reliability, I suggest creating a constant that contains all of the bits.

const int ReallyBigEnum WickedAwesomeOptions = ReallyBigEnum.FirstOption | ReallyBigEnum.AnotherOption;
...
if (flag & WickedAwesomeOptions == WickedAwesomeOptions) { ... }

Some of the redundancy is still there, but it is not fragile or confusing, and it is easy to maintain.

If the bit combination applies broadly, then you can add it to the enum itself.

[Flags]
enum ReallyBigEnum
{
    FirstOption = 1,
    AnotherOption = 2,
    WickedAwesomeOptions = FirstOption | AnotherOption,
}
....
if (flag & ReallyBigEnum.WickedAwesomeOptions == ReallyBigEnum.WickedAwesomeOptions) { ... }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文