检查枚举是否包含多个标志



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

[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

注意,我不在乎"实例"包含哪些标志,我只想知道是否有不止一个。

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

此外,我真的不想使用类似以下的东西:

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;

在上面的代码块中,我们通过使用计算其操作数的逐位逻辑AND的flag & (flag-1)) != 0(&运算符(进行检查来检查flag是否不是2的幂。如果只有一个标志集,那么我们假设该值是二的幂,否则它是非二的幂。

或者,如果你不想要一个助手功能,只需在任何地方执行该检查:

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

有关bitwise的更多信息,请点击此处查看更多信息。

参考文献:

位和移位运算符(C#参考(

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

以下示例定义了一个扩展方法帮助程序,当设置了多个标志时,它返回true

HelperExtensions.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
}

程序.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'
}

您可以在中使用Enum.GetValuesEnum.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可能不是合适的解决方案,但它非常可靠、干净,并使代码非常明显和富有表现力

参考:

C#Enum.HasFlag与位AND运算符检查

最新更新