官方文章內容:FlagsAttribute 和 Enum 的指導方針
- 將列舉常數定義為2的乘冪,也就是1、2、4、8 等等。 這表示結合的列舉常數中的個別旗標不會重迭
- 請考慮建立常用旗標組合的列舉常數。 例如,如果您有一個用於包含列舉常數和之檔案 i/o 作業的列舉 Read = 1 Write = 2 ,請考慮建立列舉常數 ReadWrite = Read OR Write ,其中結合了 Read 和 Write 旗標。 此外,在某些情況下,用來結合旗標的位 OR 運算可能會被視為一種簡單的概念
- 如果您定義負數作為旗標列舉常數,因為有許多旗標位置可能設定為1,這可能會讓您的程式碼變得令人困惑,並鼓勵程式碼錯誤,請務必謹慎使用
- 測試旗標是否設定在數值中的方便方式,是在數值和旗標列舉常數之間執行位 AND 運算,將數值中的所有位設定為零,而不會對應至旗標,然後測試該運算的結果是否等於旗標列舉常數
- 用作 None 值為零之旗標列舉常數的名稱。 您無法使用 None 位 and 運算中的列舉常數來測試旗標,因為結果一律為零。 不過,您可以在數值和列舉常數之間執行邏輯(而非位比較), None 以判斷是否已設定數值中的任何位。如果您建立一個值列舉,而不是旗標列舉,則建立列舉常數仍然是值得的 None 。 原因是,通用語言執行時間預設會將用於列舉的記憶體初始化為零。 因此,如果您未定義其值為零的常數,則在建立時,列舉會包含不合法的值。如果您的應用程式有明顯的預設情況,您的應用程式需要表示,請考慮使用其值為零的列舉常數來表示預設值。 如果沒有預設案例,請考慮使用值為零的列舉常數,表示不是任何其他列舉常數所表示的大小寫
- 請勿只定義列舉值來鏡像列舉本身的狀態。 例如,請勿定義只標示列舉結尾的列舉常數。 如果您需要判斷列舉的最後一個值,請明確檢查該值。 此外,如果範圍內的所有值都有效,您可以針對第一個和最後一個列舉的常數執行範圍檢查
- 請勿指定保留給未來使用的列舉常數
- 當您定義採用列舉常數作為值的方法或屬性時,請考慮驗證值。 原因是,您可以將數值轉換成列舉型別,即使該數值未在列舉中定義
using System;
namespace EnumFlags
{
class Program
{
static void Main(string[] args)
{
Days days = Days.Saturday;
Console.WriteLine($"初始值:{days}");
days = days.Add(Days.Sunday);
Console.WriteLine($"把星期日加入:{days}");
days = days.Remove(Days.Saturday);
Console.WriteLine($"把星期六移除:{days}");
Console.WriteLine($"星期六日是否同時存在:{days.IsSatAndSunBoth()}");
Console.WriteLine($"星期六日是否存在一日:{days.IsSatOrSunExists()}");
}
}
// 沒有特別宣告的話,Enum 預設是 int
[Flags]
public enum Days
{
Monday = 1,
Tuesday = 2 ,
Wednesday = 4,
Thursday = 8 ,
Friday = 16,
Saturday = 32,
Sunday = 64,
All = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
};
public static class ExtDays
{
public static Days Add(this Days source, Days flagAdd)
{
return source | flagAdd;
}
public static Days Remove(this Days source, Days flagRemove)
{
return source & ~flagRemove;
}
// 星期六日是否同時存在
public static bool IsSatAndSunBoth(this Days value)
{
return value.HasFlag(Days.Saturday | Days.Sunday);
}
// 星期六日是否存在一日
public static bool IsSatOrSunExists(this Days value)
{
return value.HasFlag(Days.Saturday) || value.HasFlag(Days.Sunday);
}
}
}
一開始練習時,因為是根據官方文章把 Enum 值,從 0 開始往後編,偏偏又用 [值為 0 的列舉] 來初始化,FlagAttribute 怎麼都加不上去,閱讀 [FlagsAttribute 指方針] 才發現到問題點
用作 None 值為零之旗標列舉常數的名稱。 您無法使用 None 位 and 運算中的列舉常數來測試旗標,因為結果一律為零。 不過,您可以在數值和列舉常數之間執行邏輯(而非位比較), None 以判斷是否已設定數值中的任何位。
如果您建立一個值列舉,而不是旗標列舉,則建立列舉常數仍然是值得的 None 。 原因是,通用語言執行時間預設會將用於列舉的記憶體初始化為零。 因此,如果您未定義其值為零的常數,則在建立時,列舉會包含不合法的值。
如果您的應用程式有明顯的預設情況,您的應用程式需要表示,請考慮使用其值為零的列舉常數來表示預設值。 如果沒有預設案例,請考慮使用值為零的列舉常數,表示不是任何其他列舉常數所表示的大小寫。
沒有留言:
張貼留言