これを行う従来の方法は、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
およびUnset
方法が、同等物を持っているように見えません。ですから、このクラスにはいくつかのメリットがあると私は言います。
注:enumの使用は、この問題に取り組むための従来の方法にすぎません。上記のすべてのコードを完全に変換して、代わりにintを使用することもできます。