我正在尝试检查"枚举实例"是否包含多个标志。
[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.GetValues
和Enum.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运算符检查