【问题标题】:Check if an enum contains more than one flag [duplicate]检查枚举是否包含多个标志[重复]
【发布时间】:2020-02-29 14:44:06
【问题描述】:

我正在尝试检查“枚举实例”是否包含多个标志。

[Flags]
public enum Foo 
{
  Bar = 1,
  Far = 2
}
var multiState = Foo.Bar | Foo.Far;

MoreThanOneFlag(multiState); // True

var singleState = Foo.Bar;

MoreThanOneFlag(singleState); // False

此外,我真的不想使用以下内容:

var state = Foo.Bar | Foo.Far;

Console.WriteLine(state.ToString().Count(x => x == ',') > 0); // True

注意,我不关心“实例”包含哪些标志,我只想知道是否有多个。

【问题讨论】:

  • 可能有很多重复,比如this你可以使用&操作符或者HasFlag方法
  • 执行位操作...bool value = (multiState & (multiState -1)) != 0;
  • @Çöđěxěŕ 这实际上正是我正在寻找的。可悲的是,我刚刚注意到我本可以搜索设置位,真可惜。
  • @Çöđěxěŕ 这应该是答案而不是评论。

标签: c# enums enum-flags


【解决方案1】:

我正在尝试检查“枚举实例”是否包含多个标志。 我不在乎“实例”包含哪些标志,我只想知道是否有多个

此外,我真的不想使用以下内容:

 var state = Foo.Bar | Foo.Far;
 Console.WriteLine(state.ToString().Count(x => x == ',') > 0); // True

有不止几种不同的方法可以完成你想要的,我建议做一些(按位)检查:

 public static bool MoreThanOneFlag<TValue>(TValue flag) where TValue : Enum => (Convert.ToInt32(flag) & (Convert.ToInt32(flag) - 1)) != 0;

在上面的代码块中,我们检查flag 是否不是2 的幂,方法是使用flag &amp; (flag-1)) != 0(& 运算符)计算其操作数的按位逻辑与。如果只设置了一个标志,我们假设该值将是 2 的幂,否则它是非 2 的幂。

或者,如果您不想要辅助函数,只需在任何地方执行该检查:

 bool value = (multiState & (multiState -1)) != 0;

有关按位的更多信息,请点击此处please check out

参考文献:

Bitwise and shift operators (C# reference)

【讨论】:

  • 我喜欢它!不过,您不需要使用 Convert.ToInt32。只需转换为 int 即可。如果您真的很完整,则必须检查整数类型并将其用于值。不过,超出了这个范围。 :-)
【解决方案2】:

您可以对enum 值使用二进制对数函数,然后检查结果是否为整数。

下面的例子定义了一个扩展方法助手,当设置了多个标志时返回true

HelperExtenxsions.cs

public static class HelperExtenxsions
{
  public static bool HasMultipleFlags(this IConvertible enumValue) 
  {
    return Math.Log(enumValue.ToInt32(CultureInfo.InvariantCulture.NumberFormat), 2) % 1 != 0;
  }
}

Foo.cs

[Flags]
public enum Foo 
{
  Bar = 1,
  Far = 2
}

Program.cs

public static void Main()
{ 
  var enumValue = Foo.Bar | Foo.Far; 
  Console.WriteLine(enumValue.HasMultipleFlags()); // Prints 'True'

  enumValue = Foo.Bar;
  Console.WriteLine(enumValue.HasMultipleFlags()); // Prints 'False'
}

【讨论】:

  • 枚举是现代 c# 中的有效约束。你可以做 TEnum : Enum
  • 是的,正确的。但我认为你不能简单地将Enum 转换为使用强制转换的整数值。
【解决方案3】:

您可以使用Enum.GetValues in conjunctionEnum.HasFlag(Enum) 来迭代每个常量 并确定是否在当前实例中设置了位字段和返回它的计数。

[Flags]
public enum Foo
{
  One = 1,
  Two = 2,
  Four = 4,
  Eight = 8
}

var state1 = Foo.One;
var state2 = Foo.Two;//
var state3 = Foo.One | Foo.Two; 
var state4 = Foo.Two | Foo.Four;

Console.WriteLine(MoreThanOneFlag(state1));//false
Console.WriteLine(MoreThanOneFlag(state2));//false
Console.WriteLine(MoreThanOneFlag(state3));//true
Console.WriteLine(MoreThanOneFlag(state4));// true
private static bool MoreThanOneFlag<TEnum>(TEnum state) where TEnum : Enum
{
  var names = Enum.GetValues(typeof(TEnum));
  var Flagcounter = names.OfType<TEnum>().Where(x=>state.HasFlag((TEnum)x)).Count();
  return Flagcounter > 1 ? true : false;
}

注意:如果您的应用程序需要性能,Enum.HasFlags 可能不是合适的解决方案,但它是很多 reliable, clean, and makes the code very obvious and expressive

参考:

C# Enum.HasFlag vs. Bitwise AND Operator Check

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多