1. ホーム
  2. c#

[解決済み] C#の[Flags]Enum属性の意味とは?

2022-03-18 07:54:55

質問

時々、以下のようなenumを見かけます。

[Flags]
public enum Options 
{
    None    = 0,
    Option1 = 1,
    Option2 = 2,
    Option3 = 4,
    Option4 = 8
}

が具体的にどのようなものなのか理解できません。 [Flags] 属性は何をするのですか?

どなたか、良い説明や例を掲載できる方はいらっしゃいませんか?

どのように解決するのですか?

その [Flags] 属性は、enumerable が単一の値ではなく、取り得る値の集まりを表す場合に使用されるべきです。このようなコレクションは、例えば、ビット演算子でよく使用されます。

var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;

ただし [Flags] 属性 ではありません。 は、それ自体でこれを可能にします。 .ToString() メソッドを使用します。

enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }

...

var str1 = (Suits.Spades | Suits.Diamonds).ToString();
           // "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
           // "Spades, Diamonds"

また [Flags] はしません。 は自動的に列挙値を2の累乗にします。もし、数値を省略した場合、enumはビット演算で期待されるような動作をしません。なぜなら、デフォルトでは、値は0から始まり、増加するからです。

宣言が正しくない。

[Flags]
public enum MyColors
{
    Yellow,  // 0
    Green,   // 1
    Red,     // 2
    Blue     // 3
}

このように宣言すると、値は、Yellow = 0, Green = 1, Red = 2, Blue = 3 となります。これではフラグとして使い物にならない。

以下は正しい宣言の例です。

[Flags]
public enum MyColors
{
    Yellow = 1,
    Green = 2,
    Red = 4,
    Blue = 8
}

プロパティに含まれる個別の値を取り出すには、次のようにします。

if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
    // Yellow is allowed...
}

または.NET 4より前のバージョン。

if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
    // Yellow is allowed...
}

if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
    // Green is allowed...
}    

アンダーザカバー

これは、列挙に2の累乗を使ったからうまくいったのです。列挙の値は、1 と 0 のバイナリで次のように表示されます。

 Yellow: 00000001
 Green:  00000010
 Red:    00000100
 Blue:   00001000

同様に、プロパティを設定した後に 許可された色 を赤、緑、青に設定するために、バイナリビット単位のORを使用します。 | 演算子を使用します。 許容カラー はこのようになります。

myProperties.AllowedColors: 00001110

つまり、値を取得する際に、実際にはビット単位のANDを実行していることになります。 & を値に追加します。

myProperties.AllowedColors: 00001110
             MyColor.Green: 00000010
             -----------------------
                            00000010 // Hey, this is the same as MyColor.Green!

None = 0 の値

そして、その使用に関して 0 を、MSDNから引用しています。

[Flags]
public enum MyColors
{
    None = 0,
    ....
}

値がゼロであるフラグ列挙定数の名前として None を使用します。 結果は常にゼロであるため、フラグをテストするためのビット単位のAND演算でNone列挙定数を使用することはできません。 しかし、数値とNone列挙定数をビット単位ではなく論理的に比較することで、数値のビットが設定されているかどうかを判断することができます。

flags属性とその使用方法についての詳細は、以下を参照してください。 msdn msdnでフラグをデザインする