C# で enum を フラグ として 演算 & 判定 する 方法

0 件のコメント

enum を ビットフラグ として利用することはよくあると思いますが、 フラグとして利用する際、よく直面する フラグ操作(フラグ演算、判定) をまとめてみました。

目次

フラグ利用する enum の作成

ビット演算できるよう、数値は被らないように値を設定する必要があります。 おおよそ 2進数 における 各桁 が 1 となるような設定になります。 具体的には 1 (=2^0), 2 (=2^1), 4 (=2^2), 8 (=2^3), 16 (=2^4) … といった感じです。 フラグ利用する enum の場合、 Flags 属性 をつけるのもポイントです。

[Flags]
public enum Week
{
    Sunday    = 0x001,
    Monday    = 0x002,
    Tuesday   = 0x004,
    Wednesday = 0x008,
    Thursday  = 0x010,
    Friday    = 0x020,
    Saturday  = 0x040
}

上述の enum を 2進数、10進数で表に表わすと以下のようになります。

フラグ 2進数 10進数 16進数
Sunday 0000001 (2) 1 0x001
Monday 0000010 (2) 2 0x002
Tuesday 0000100 (2) 4 0x004
Wednesday 0001000 (2) 8 0x008
Thursday 0010000 (2) 16 0x010
Friday 0100000 (2) 32 0x020
Saturday 1000000 (2) 64 0x040

フラグ 演算

慣れないと難しいし、あまり使わないのでよく忘れがちですが… 基本はビット演算になります。 以下では基本となる追加と削除を例に記載します。

フラグを追加する

追加する場合、 |演算子(OR演算子) でつなげることで追加できます。

var flag = Week.Monday;
flag = flag | Week.Wednesday;

フラグを削除する

削除する場合、 &演算子(AND演算子) と ~演算子(反転演算子) の組み合わせで削除できます。

var flag = Week.Monday | Week.Wednesday;
flag = flag & ~Week.Wednesday;

フラグ 判定

どの フラグ が立っているかを判定する方法は 2通り あります。 1つは ビット演算、もう1つは HasFlags メソッド。 ビット演算 は昔からあるやり方で、ややクセがある が 速いフラグ判定方法だと思います。 新しく追加された HasFlags メソッド は簡単にフラグが立っているかどうかを判定でき、かつ、コードが読みやすい方法だと思います。

ビット演算

var flag = Week.Monday | Week.Wednesday;

// "flag" が "Monday"
if ((flag & Week.Monday) == Week.Monday )
{
    // ...
}

// "flag" が "Monday かつ Wednesday"
if ((flag & (Week.Monday | Week.Wednesday)) == (Week.Monday | Week.Wednesday))
{
    // ...
}

// "flag" が "Monday または Wednesday"
if ((flag & (Week.Monday | Week.Wednesday)) != 0)
{
    // ...
}

HasFlags メソッド

var flag = Week.Monday | Week.Wednesday;

// "flag" が "Monday"
if (flag.HasFlag(Week.Monday))
{
    // ...
}

// "flag" が "Monday かつ Wednesday"
if (flag.HasFlag(Week.Monday) && flag.HasFlag(Week.Wednesday))
{
    // ...
}

// "flag" が "Monday または Wednesday"
if (flag.HasFlag(Week.Monday) || flag.HasFlag(Week.Wednesday))
{
    // ...
}