检查标志是否包含其他标志的任何值
Check if flag contains any value of other flag
我想比较两个标志,看看它们是否有任何共同的价值。
我希望有一个扩展方法来“加速”编码(我将经常在各种枚举类型上使用它)。我该怎么办?
这段代码告诉我:
operator '&' cannot be applied to operands of type enum and enum
public enum Tag
{
Value1 = 1,
Value2 = 2,
Value3 = 4,
Value4 = 8,
Value5 = 16
}
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (me & other) != 0;
}
}
public class Program
{
public static void Main()
{
Tag flag1 = Tag.Value1 | Tag.Value2 | Tag.Value3;
Tag flag2 = Tag.Value2 | Tag.Value3 | Tag.Value4;
Console.WriteLine(flag1.HasAny(flag2)); // it should returns true. flag1.HasFlag(flag2) returns false.
}
}
我也试过这个:
return (((int)me) & ((int)other)) != 0;
但它引发了错误:
Cannot convert type 'System.Enum' to 'int'
根据这个答案 (How to convert from System.Enum to base integer?)
您需要用异常处理程序包装此代码,或者以其他方式确保两个枚举都包含一个整数。
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (Convert.ToInt32(me) & Convert.ToInt32(other)) != 0;
}
}
如果您想要一个非常通用的 HasAny
枚举扩展,您可以执行以下操作。我已经测试过这适用于枚举可以是的所有不同的底层类型。此外,如果您正在检查标志,您可能应该使用 [Flags]
属性装饰您的枚举,因此这将检查被检查的枚举是否具有该属性。
public static class FlagExtensions
{
public static bool HasAny(this Enum enumLeft, Enum enumRight)
{
if (enumLeft.GetType() != enumRight.GetType())
throw new ArgumentException("enum types should be the same");
if (!enumLeft.GetType().IsDefined(typeof(FlagsAttribute), inherit: false))
throw new ArgumentException("enum type should have the flags attribute");
dynamic enumLeftValue = Convert.ChangeType(enumLeft, enumLeft.GetTypeCode());
dynamic enumRightValue = Convert.ChangeType(enumRight, enumRight.GetTypeCode());
return (enumLeftValue & enumRightValue) != 0;
}
}
I tried this as well:
return (((int)me) & ((int)other)) != 0;
but it raises the error:
Cannot convert type 'System.Enum' to 'int'
枚举总是实现 IConvertible 并且 IConvertible 具有 'ToInt32'。所以你可以这样写:
public static class FlagExt
{
public static bool HasAny<TEnum>(this TEnum me, TEnum other)
where TEnum : Enum, IConvertible
{
return (me.ToInt32(null) & other.ToInt32(null)) != 0;
}
}
我想比较两个标志,看看它们是否有任何共同的价值。
我希望有一个扩展方法来“加速”编码(我将经常在各种枚举类型上使用它)。我该怎么办?
这段代码告诉我:
operator '&' cannot be applied to operands of type enum and enum
public enum Tag
{
Value1 = 1,
Value2 = 2,
Value3 = 4,
Value4 = 8,
Value5 = 16
}
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (me & other) != 0;
}
}
public class Program
{
public static void Main()
{
Tag flag1 = Tag.Value1 | Tag.Value2 | Tag.Value3;
Tag flag2 = Tag.Value2 | Tag.Value3 | Tag.Value4;
Console.WriteLine(flag1.HasAny(flag2)); // it should returns true. flag1.HasFlag(flag2) returns false.
}
}
我也试过这个:
return (((int)me) & ((int)other)) != 0;
但它引发了错误:
Cannot convert type 'System.Enum' to 'int'
根据这个答案 (How to convert from System.Enum to base integer?)
您需要用异常处理程序包装此代码,或者以其他方式确保两个枚举都包含一个整数。
public static class FlagExt
{
public static bool HasAny(this Enum me, Enum other)
{
return (Convert.ToInt32(me) & Convert.ToInt32(other)) != 0;
}
}
如果您想要一个非常通用的 HasAny
枚举扩展,您可以执行以下操作。我已经测试过这适用于枚举可以是的所有不同的底层类型。此外,如果您正在检查标志,您可能应该使用 [Flags]
属性装饰您的枚举,因此这将检查被检查的枚举是否具有该属性。
public static class FlagExtensions
{
public static bool HasAny(this Enum enumLeft, Enum enumRight)
{
if (enumLeft.GetType() != enumRight.GetType())
throw new ArgumentException("enum types should be the same");
if (!enumLeft.GetType().IsDefined(typeof(FlagsAttribute), inherit: false))
throw new ArgumentException("enum type should have the flags attribute");
dynamic enumLeftValue = Convert.ChangeType(enumLeft, enumLeft.GetTypeCode());
dynamic enumRightValue = Convert.ChangeType(enumRight, enumRight.GetTypeCode());
return (enumLeftValue & enumRightValue) != 0;
}
}
I tried this as well:
return (((int)me) & ((int)other)) != 0;
but it raises the error:
Cannot convert type 'System.Enum' to 'int'
枚举总是实现 IConvertible 并且 IConvertible 具有 'ToInt32'。所以你可以这样写:
public static class FlagExt
{
public static bool HasAny<TEnum>(this TEnum me, TEnum other)
where TEnum : Enum, IConvertible
{
return (me.ToInt32(null) & other.ToInt32(null)) != 0;
}
}