假设你有以下枚举类型:
enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};
现在你有一个函数,需要检查MyEnum的实例是否为C、D或F,并在满足条件时返回true。
bool IsCDF(MyEnum enumValue)
{
return //something slick
}
我记得有一种非常流畅的方法可以做位移并执行此操作,比一堆三元if语句更易读,但是我现在无论如何也想不起来了。
有人知道吗?
假设你有以下枚举类型:
enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};
现在你有一个函数,需要检查MyEnum的实例是否为C、D或F,并在满足条件时返回true。
bool IsCDF(MyEnum enumValue)
{
return //something slick
}
我记得有一种非常流畅的方法可以做位移并执行此操作,比一堆三元if语句更易读,但是我现在无论如何也想不起来了。
有人知道吗?
bool IsCDF(MyEnum enumValue)
{
return new[]{MyEnum.C, MyEnum.D, MyEnum.F}.Contains(enumValue);
}
[Flags]
枚举类型,你可以为每个枚举值分配一个不同的位值(1、2、4、8、16……)。然后,你可以使用位运算来确定一个值是否是可能值集合中的一项。
因此,要检查它是否为 C、D 或 F:
bool IsCDF(MyEnum enumValue)
{
return ((enumValue & (MyEnum.C | MyEnum.D | MyEnum.F)) != 0);
}
或者使用 HasFlag()
(效率较低但更易读):
bool IsCDF(MyEnum enumValue)
{
return enumValue.HasFlag(MyEnum.C | MyEnum.D | MyEnum.F);
}
请注意,这种方法对于值为0(在您的示例中为“A”)不起作用,您必须小心确保所有枚举值解析为唯一的比特值(即非零二次幂)。
这种方法的优点是:
便捷提示:在定义[Flags]枚举时,请使用左移(<<)使比特值更清晰(并且更难出错),尤其是对于高阶位。
[Flags]
enum MyEnum
{
A = 1 << 0, // Equivalent to 1
B = 1 << 1, // Equivalent to 2
C = 1 << 2, // Equivalent to 4
D = 1 << 3, // Equivalent to 8
…
Big = 1 << 26, // Equivalent to 67108864
}
我可能会使用Unconstrained Melody来保持代码整洁:
if (value.HasAny(MyEnum.C | MyEnum.D | MyEnum.E))
{
...
}
我会将"C、D或E"提取为命名常量,可能在枚举本身中,如果它有意义的话:
这是我创建的一个扩展,它可以让你查看给定的枚举值是否在可能的枚举值列表中。
using System.Linq;
public static class ExtensionMethods
{
public static bool IsAny<T>(this T value, params T[] choices)
where T : Enum
{
return choices.Contains(value);
}
}
用法
bool IsCDF(MyEnum enumValue)
{
return enumValue.IsAny(MyEnum.C, MyEnum.D, MyEnum.F);
}
也许这个扩展类对你有用:
public static class Flags
{
/// <summary>
/// Checks if the type has any flag of value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool HasAny<T>(this System.Enum type, T value)
{
try
{
return (((int) (object) type & (int) (object) value) != 0);
}
catch
{
return false;
}
}
/// <summary>
/// Checks if the value contains the provided type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool Has<T>(this System.Enum type, T value)
{
try
{
return (((int)(object)type & (int)(object)value) == (int)(object)value);
}
catch
{
return false;
}
}
/// <summary>
/// Checks if the value is only the provided type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool Is<T>(this System.Enum type, T value)
{
try
{
return (int)(object)type == (int)(object)value;
}
catch
{
return false;
}
}
/// <summary>
/// Appends a value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static T Add<T>(this System.Enum type, T value)
{
try
{
return (T)(object)(((int)(object)type | (int)(object)value));
}
catch (Exception ex)
{
throw new ArgumentException(
string.Format(
"Could not append value from enumerated type '{0}'.",
typeof(T).Name
), ex);
}
}
/// <summary>
/// Appends a value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static void AddTo<T>(this System.Enum type, ref T value)
{
try
{
value = (T)(object)(((int)(object)type | (int)(object)value));
}
catch (Exception ex)
{
throw new ArgumentException(
string.Format(
"Could not append value from enumerated type '{0}'.",
typeof(T).Name
), ex);
}
}
/// <summary>
/// Removes the value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static T Remove<T>(this System.Enum type, T value)
{
try
{
return (T)(object)(((int)(object)type & ~(int)(object)value));
}
catch (Exception ex)
{
throw new ArgumentException(
string.Format(
"Could not remove value from enumerated type '{0}'.",
typeof(T).Name
), ex);
}
}
/// <summary>
/// Removes the value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="type"></param>
/// <param name="value"></param>
/// <returns></returns>
public static void RemoveFrom<T>(this System.Enum type, ref T value)
{
try
{
value = (T)(object)(((int)(object)type & ~(int)(object)value));
}
catch (Exception ex)
{
throw new ArgumentException(
string.Format(
"Could not remove value from enumerated type '{0}'.",
typeof(T).Name
), ex);
}
}
}
return (enumValue & MyEnum.C == MyEnum.C)
|| (enumValue & MyEnum.D == MyEnum.D)
|| (enumValue & MyEnum.F == MyEnum.F);