传统的做法是在枚举类型上使用
Flags
属性:
[Flags]
public enum Names
{
None = 0,
Susan = 1,
Bob = 2,
Karen = 4
}
然后,您可以按以下方式检查特定名称:
Names names = Names.Susan | Names.Bob
// evaluates to true
bool susanIsIncluded = (names & Names.Susan) != Names.None
// evaluates to false
bool karenIsIncluded = (names & Names.Karen) != Names.None
逻辑位运算组合可能很难记住,所以我通过一个FlagsHelper
类来简化我的生活*:
public static class FlagsHelper
{
public static bool IsSet<T>(T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
return (flagsValue & flagValue) != 0;
}
public static void Set<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
flags = (T)(object)(flagsValue | flagValue);
}
public static void Unset<T>(ref T flags, T flag) where T : struct
{
int flagsValue = (int)(object)flags;
int flagValue = (int)(object)flag;
flags = (T)(object)(flagsValue & (~flagValue));
}
}
这将允许我将上述代码重写为:
Names names = Names.Susan | Names.Bob;
bool susanIsIncluded = FlagsHelper.IsSet(names, Names.Susan);
bool karenIsIncluded = FlagsHelper.IsSet(names, Names.Karen);
请注意,我也可以通过以下方式将Karen
添加到集合中:
FlagsHelper.Set(ref names, Names.Karen)
我可以用类似的方式删除Susan
:
FlagsHelper.Unset(ref names, Names.Susan);
*正如Porges所指出的那样,IsSet
方法的等价物已经存在于.NET 4.0中:Enum.HasFlag
。然而,Set
和Unset
方法似乎没有相应的方法;因此我仍然认为这个类具有一定的价值。
注意:使用枚举只是解决这个问题的传统方式。你完全可以将上述所有代码转换为使用整数,它也能够正常工作。