[英]C#: Best way to check against a set of Enum Values?
suppose you have enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};
假设你有
enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};
At some point you have a function that will check an instance of MyEnum and return true if it is C,D, or F在某些时候,您有一个 function 将检查 MyEnum 的实例,如果它是 C、D 或 F,则返回 true
bool IsCDF(MyEnum enumValue)
{
return //something slick
}
I remember that there was some really slick way to do bit shifting and preform this operation that read way better than a bunch of ternary if statements but for the life of me I can't remember what it is.我记得有一些非常巧妙的方法可以进行位移和执行这个操作,它比一堆三元 if 语句更好读,但是对于我的生活,我不记得它是什么。
Anyone know?有人知道吗?
bool IsCDF(MyEnum enumValue)
{
return new[]{MyEnum.C, MyEnum.D, MyEnum.F}.Contains(enumValue);
}
If you make it a [Flags]
enum, you can assign a different bit value (1, 2, 4, 8, 16...) to each enumerated value. 如果将其设为
[Flags]
枚举,则可以为每个枚举值分配不同的位值(1,2,4,8,1 ...)。 Then you can use a bitwise operation to determine if a value is one of a set of possible values. 然后,您可以使用按位运算来确定值是否是一组可能值中的一个。
So, to see if it is C, D, or F: 所以,看看它是C,D还是F:
bool IsCDF(MyEnum enumValue)
{
return ((enumValue & (MyEnum.C | MyEnum.D | MyEnum.F)) != 0);
}
or using HasFlag()
(less efficient but more readable): 或使用
HasFlag()
(效率较低但更易读):
bool IsCDF(MyEnum enumValue)
{
return enumValue.HasFlag(MyEnum.C | MyEnum.D | MyEnum.F);
}
Note that this will not work for a value of 0 (in your example, 'A'), and you must be careful that all enum values resolve to unique bit values (ie non-zero powers of two). 请注意,这不适用于值0(在您的示例中为'A'),并且必须注意所有枚举值都会解析为唯一位值(即非零幂的2)。
The advantages of this approach are: 这种方法的优点是:
Handy hint: When defining [Flags] enums, use left-shift ( <<
) to make the bit values clearer (and much harder to get wrong) especially for higher-order bits: 方便提示:在定义[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
}
I'd possibly use Unconstrained Melody as a way of keeping things tidy: 我可能会使用无约束旋律作为保持整洁的一种方式:
if (value.HasAny(MyEnum.C | MyEnum.D | MyEnum.E))
{
...
}
I'd probably extract the "C, D or E" bit into a named constant - possibly in the enum itself, if it had meaning: 我可能会将“C,D或E”位提取到一个命名常量中 - 可能在枚举本身中,如果它有意义:
May be you are thinking of FlagsAttribute . 可能你在考虑FlagsAttribute 。 Look at here and here for some examples.
在这里和这里看一些例子。
You could use Enum.HasFlag Method 您可以使用Enum.HasFlag方法
Maybe this extension class is usefull for you: 也许这个扩展类对你有用:
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);
}
}
}
Here is an extension I created that allows you to see if your given Enum value is in a variable list of possible choices of Enum values.这是我创建的一个扩展,它允许您查看给定的 Enum 值是否在 Enum 值的可能选择的变量列表中。
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);
}
}
Usage用法
bool IsCDF(MyEnum enumValue)
{
return enumValue.IsAny(MyEnum.C, MyEnum.D, MyEnum.F);
}
return (enumValue & MyEnum.C == MyEnum.C)
|| (enumValue & MyEnum.D == MyEnum.D)
|| (enumValue & MyEnum.F == MyEnum.F);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.