列舉為標誌
FlagsAttribute
可以應用於列舉,改變 ToString()
的行為以匹配列舉的性質:
[Flags]
enum MyEnum
{
//None = 0, can be used but not combined in bitwise operations
FlagA = 1,
FlagB = 2,
FlagC = 4,
FlagD = 8
//you must use powers of two or combinations of powers of two
//for bitwise operations to work
}
var twoFlags = MyEnum.FlagA | MyEnum.FlagB;
// This will enumerate all the flags in the variable: "FlagA, FlagB".
Console.WriteLine(twoFlags);
因為 FlagsAttribute
依賴於列舉常量是 2(或它們的組合)的冪,並且列舉值最終是數值,所以你受到基礎數值型別的大小的限制。你可以使用的最大可用數字型別是 UInt64
,它允許你指定 64 個不同(非組合)標誌列舉常量。enum
關鍵字預設為基礎型別 int
,即 Int32
。編譯器將允許宣告寬於 32 位的值。這些將在沒有警告的情況下環繞並導致兩個或更多具有相同值的列舉成員。因此,如果列舉是為了容納超過 32 個標誌的位集,則需要明確指定更大的型別:
public enum BigEnum : ulong
{
BigValue = 1 << 63
}
儘管標誌通常只有一個位,但它們可以組合成命名的集合以便於使用。
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
為了避免拼寫出 2 的冪的十進位制值,左移運算子(<<) 也可用於宣告相同的列舉
[Flags]
enum FlagsEnum
{
None = 0,
Option1 = 1 << 0,
Option2 = 1 << 1,
Option3 = 1 << 2,
Default = Option1 | Option3,
All = Option1 | Option2 | Option3,
}
從 C#7.0 開始,也可以使用二進位制文字 。
要檢查列舉變數的值是否設定了某個標誌,可以使用 HasFlag
方法。假設我們有
[Flags]
enum MyEnum
{
One = 1,
Two = 2,
Three = 4
}
和一個 value
var value = MyEnum.One | MyEnum.Two;
使用 HasFlag
,我們可以檢查是否設定了任何標誌
if(value.HasFlag(MyEnum.One))
Console.WriteLine("Enum has One");
if(value.HasFlag(MyEnum.Two))
Console.WriteLine("Enum has Two");
if(value.HasFlag(MyEnum.Three))
Console.WriteLine("Enum has Three");
我們也可以迭代 enum 的所有值來獲取所有設定的標誌
var type = typeof(MyEnum);
var names = Enum.GetNames(type);
foreach (var name in names)
{
var item = (MyEnum)Enum.Parse(type, name);
if (value.HasFlag(item))
Console.WriteLine("Enum has " + name);
}
要麼
foreach(MyEnum flagToCheck in Enum.GetValues(typeof(MyEnum)))
{
if(value.HasFlag(flagToCheck))
{
Console.WriteLine("Enum has " + flagToCheck);
}
}
這三個例子都將列印出來:
Enum has One
Enum has Two