列挙型(enum)をビットフラグとして判定する方法と演算する方法を紹介します。
目次
ビットフラグとして使用する列挙型(enum)の作成
ビットフラグとして使用する列挙型(enum)を作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// ビットフラグとして使用する列挙型 [Flags] private enum BitFlag { Black = 1, // 0x001 Red = 2, // 0x002 Green = 4, // 0x004 Blue = 8, // 0x008 Orange = 16, // 0x010 Pink = 32, // 0x020 Purple = 64, // 0x040 White = 128 // 0x080 } |
ビットフラグとして使用する列挙型にはFlagsAttribute属性の[Flags]を指定(付与)します。
ここではBitFlagという名前の列挙型を作成しています。
列挙型のメンバー定数には「1, 2, 4, 8, 16…」と、どれを足しても被らないように1と2の冪乗(べきじょう)となる値を指定します。例えば、上記のメンバーに3の値を持つメンバーがあると、1 + 2 = 3となってしまうので、正しくビットフラグが判別できません。ですので、2の冪乗の値を使用します。
以下に上記のBitFlg列挙型のメンバを10進数、16進数、2進数で表した一覧を記載しておきます。
メンバー | 10進数 | 16進数 | 2進数 |
---|---|---|---|
Black | 1 | 0x001 | 00000001 |
Red | 2 | 0x002 | 00000010 |
Green | 4 | 0x004 | 00000100 |
Blue | 8 | 0x008 | 00001000 |
Orange | 16 | 0x010 | 00010000 |
Pink | 32 | 0x020 | 00100000 |
Purple | 64 | 0x040 | 01000000 |
White | 128 | 0x080 | 10000000 |
C#のコードでビットフラグを作成する場合は、分かりづらければ10進数ではなく16進数で記述すると、少し分かりやすくなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// ビットフラグとして使用する列挙型 [Flags] private enum BitFlag { Black = 0x001, // 1 Red = 0x002, // 2 Green = 0x004, // 4 Blue = 0x008, // 8 Orange = 0x010, // 16 Pink = 0x020, // 32 Purple = 0x040, // 64 White = 0x080 // 128 } |
この列挙型のメンバーの記述方法については、個人の好みがありますので、自分がわかりやすい方法(またはチームのメンバー同士で決めたルール)にしてください。
ビットフラグの判定
ビットフラグの判定の仕方は、ビット演算を行って判別する方法と、列挙型のEnumクラスのHasFlagメソッドを使用する方法の2通りになります。
ビット演算を行って判定する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
・・ BitFlag bitFlag = BitFlag.Red | BitFlag.Blue; // bitFlag が「Red」かどうか if ((bitFlag & BitFlag.Red) == BitFlag.Red) { // 「Red」の場合の処理... Console.WriteLine("Red"); } // bitFlag が「Red」かつ「Blue」かどうか if ((bitFlag & (BitFlag.Red | BitFlag.Blue)) == (BitFlag.Red | BitFlag.Blue)) { // 「Red」かつ「Blue」の場合の処理... Console.WriteLine("Red and Blue"); } // bitFlag が「Red」または「Blue」かどうか if ((bitFlag & (BitFlag.Red | BitFlag.Blue)) != 0) { // 「Red」または「Blue」の場合の処理... Console.WriteLine("Red or Blue"); } |
ビット演算では、「&演算子(AND演算子)」と「|演算子(OR演算子)」を使ってビットフラグを判定します。
HasFlagメソッドを使用して判定する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
BitFlag bitFlag = BitFlag.Red | BitFlag.Blue; // bitFlag が「Red」かどうか if (bitFlag.HasFlag(BitFlag.Red)) { // 「Red」の場合の処理... Console.WriteLine("Red"); } // bitFlag が「Red」かつ「Blue」かどうか if (bitFlag.HasFlag(BitFlag.Red) && bitFlag.HasFlag(BitFlag.Blue)) { // 「Red」かつ「Blue」の場合の処理... Console.WriteLine("Red and Blue"); } // bitFlag が「Red」または「Blue」かどうか if (bitFlag.HasFlag(BitFlag.Red) || bitFlag.HasFlag(BitFlag.Blue)) { // 「Red」または「Blue」の場合の処理... Console.WriteLine("Red or Blue"); } |
HasFlagメソッドについては.NET Framework4.0からで追加されたメソッドになりますので、対象のフレームワークが.NET Framework4.0以降(.NET Core, .NET Standardを含む)であれば使用できます。
HasFlagメソッドは、現在のインスタンスで、1つ以上のビットフィールドが設定されているかどうかを判断して、戻り値にbool型の値(true/false)を返してくれます。ビット演算に慣れていない方には、コードが読みやすくておすすめです。処理速度としてはビット演算を使用した方が速いかもしれません。
ビットフラグの演算
ビットフラグの演算として、フラグを追加する方法と、フラグを削除する方法を紹介します。
ビットフラグを追加する
1 2 3 4 |
// ビットフラグを追加する bitFlag = bitFlag | BitFlag.Green; // または bitFlag |= BitFlag.Orange; |
ビットフラグを追加するには「|演算子(OR演算子)」を使用します。
フラグを「|演算子(OR演算子)」でつなげることで追加できます。
ビットフラグを削除する
1 2 3 4 |
// ビットフラグを削除する bitFlag = bitFlag & ~BitFlag.Green; // または bitFlag &= ~BitFlag.Orange; |
ビットフラグを削除するには「&演算子(AND演算子)」と「~演算子(反転演算子)」を使用します。
「~演算子(反転演算子)」を付けたフラグを「&演算子(AND演算子)」でつなげることで削除できます。
ビットフラグの演算は、慣れるまでは難しいというか、ややこしいというか、頭にすんなりとは入ってこないものです。また、頻繁に使うものでもないので忘れてしまうことも多々ありますが、基本はビット演算なので、これを機会に覚えてしまってください。