過去に出くわした面白い使い方を紹介します。この例は、「 [Flags] Enum AttributeはC#で何を意味するのですか?」という質問に対する補足回答から恥知らずにコピーされています。
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
1, 2, 4, 8, ...
これは、特に17個のフラグを超えた場合に、リテラル値を書き込むよりも簡単に拡張できます。
トレードオフは、31を超えるフラグ(1 << 30
)が必要な場合は、列挙型を符号付き整数よりも高い上限を持つものとして指定するように注意する必要があります(public enum MyEnum : ulong
たとえば、として宣言することにより、 64フラグ)。それの訳は...
1 << 29 == 536870912
1 << 30 == 1073741824
1 << 31 == -2147483648
1 << 32 == 1
1 << 33 == 2
対照的に、列挙値を直接2147483648に設定すると、コンパイラはエラーをスローします。
ClickRickが指摘しているように、列挙型がulongから派生している場合でも、ビットシフト操作はulongに対して実行する必要があります。そうしないと、列挙型の値が壊れます。
[Flags]
public enum MyEnum : ulong
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3,
// Compiler error:
// Constant value '-2147483648' cannot be converted to a 'ulong'
// (Note this wouldn't be thrown if MyEnum derived from long)
ThirtySecond = 1 << 31,
// so what you would have to do instead is...
ThirtySecond = 1UL << 31,
ThirtyThird = 1UL << 32,
ThirtyFourth = 1UL << 33
}