执行此操作的传统方法是在 a 上使用Flags
属性enum
:
[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
类*让自己的生活更轻松:
// The casts to object in the below code are an unfortunate necessity due to
// C#'s restriction against a where T : Enum constraint. (There are ways around
// this, but they're outside the scope of this simple illustration.)
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
andUnset
方法似乎没有等价物。所以我仍然会说这门课有一些优点。
注意:使用枚举只是解决此问题的常规方法。您可以完全将上述所有代码转换为使用 int,它也可以正常工作。