簡體   English   中英

為什么[Flag]'枚舉從0開始並遞增1?

[英]Why does [Flag]'d enums start at 0 and increment by 1?

編輯:似乎大多數人誤解了我的問題。

我知道枚舉是如何運作的,我知道二進制。 我想知道為什么帶有[Flags]屬性的枚舉是按原樣設計的。

原帖:

這可能是重復的,但我沒有找到任何其他帖子,所以這里。

我打賭它背后有一些很好的理由,我發現它有點容易出錯。

[Flag]
public enum Flagged
{
  One, // 0
  Two, // 1
  Three, // 2
  Four, // 3
}

Flagged f; // Defaults to Flagged.One = 0
f = Flagged.Four;
(f & Flagged.One) != 0; // Sure.. One defaults to 0
(f & Flagged.Two) != 0; // 3 & 1 == 1
(f & Flagged.Three) != 0; // 3 & 2 == 2

如果做到這樣的話會不會更有意義?

[Flag]
public enum Flagged
{
  One = 1 << 0, // 1
  Two = 1 << 1, // 2
  Three = 1 << 2, // 4
  Four = 1 << 3, // 8
}

Flagged f; // Defaults to 0
f = Flagged.Four;
(f & Flagged.One) != 0; // 8 & 1  == 0
(f & Flagged.Two) != 0; // 8 & 2 == 0
(f & Flagged.Three) != 0; // 8 & 4 == 0
(f & Flagged.Four) != 0; // 8 & 8 == 8

當然..我不太確定它應該如何處理這樣的自定義標志

[Flag]
public enum Flagged
{
   One, // 1
   Two, // 2
   LessThanThree = One | Two,
   Three, // 4? start from Two?
   LessThanFour = Three | LessThanThree,
   Three, // 8? start from Three?
}

該規范提供了一些指導

定義2的冪的枚舉常量,即1,2,4,8等。 這意味着組合枚舉常量中的各個標志不重疊。

但這應該是自動完成的,因為我打賭你永遠不會想要我的第一個例子。 請賜教:)

Flags屬性僅用於將值格式化為多個值。 位操作適用於具有或不具有該屬性的基礎類型。

除非明確給出其他值,否則枚舉的第一項為零。 通常最佳做法是為標志枚舉設置零值,因為它為零值提供了語義含義,例如“無標志”或“關閉”。 這有助於維護代碼,因為它可能意味着代碼的意圖(盡管注釋也實現了這一點)。

除此之外,您和您的設計是否取決於您是否需要零值。

由於標志枚舉仍然只是枚舉( FlagsAttribute只是指示調試器將值解釋為其他值的組合),因此枚舉中的下一個值總是比前一個值多一個。 因此,您應明確指定位值,因為您可能希望將組合表示為其他值的按位或。

也就是說,想象一個標志枚舉的語法,要求所有按位組合放在枚舉定義的末尾或以某種方式標記,這樣編譯器就知道如何處理其他所有內容,這並不是不合理的。

例如(假設有一個flags關鍵字,我們在北半球),

flags enum MyFlags
{
   January,
   February,
   March,
   April,
   May,
   June,
   July,
   August,
   September,
   October,
   November,
   December,
   Winter = January | February | March
   Spring = April | May | June
   Summer = July | August | September
   Autumn = October | November | December
} 

使用此語法,編譯器可以自己創建0值,並自動為其他值分配標志。

屬性是[Flags]而不是[Flag],並沒有什么神奇之處。 它似乎唯一影響的是ToString方法。 指定[標志]時,值以逗號分隔。 由您指定值以使其在位字段中使用有效。

注釋的C#3規范中沒有任何內容。 我想在注釋的C#4規范中可能會有一些東西 - 我不確定。 (我想我自己開始編寫這樣的注釋,但后來刪除了它。)

這對於簡單的情況很好,但是一旦你開始添加額外的標志,它就會變得有點棘手:

[Flags]
enum Features
{
    Frobbing, // 1
    Blogging, // 2 
    Widgeting, // 4
    BloggingAndWidgeting = Frobbing | Blogging, // 6
    Mindnumbing // ?
}

Mindnumbing應該有什么價值? 下一個沒用過的位? 如果你設置一個固定的整數值呢?

我同意這是一種痛苦。 也許可以制定一些合理的規則......但我想知道復雜性與價值平衡是否真的有效。

簡而言之, Flags是一個屬性。 它在創建枚舉之后才會應用,因此不會更改分配給枚舉的值。

話雖如此,MSDN頁面Designing Flags Enumerations說:

對標志枚舉的值使用2的冪,以便可以使用按位OR運算自由組合它們。

重要提示:如果不使用2的冪或2的冪組合,則按位運算將無法按預期工作。

同樣, FlagsAttribute的頁面說

定義2的冪的枚舉常量,即1,2,4,8等。 這意味着組合枚舉常量中的各個標志不重疊。

在C中,可以(ab)使用預處理器自動生成2次冪枚舉。 如果有一個宏make_things擴展為“make_thing(flag1)make_thing(flag2)make_thing(flag3)”等,則可以多次調用該宏,並使用不同的make_thing定義,以實現2的冪國旗名稱序列以及其他一些好東西。

例如,首先將make_thing(x)定義為“LINEAR_ENUM _ ## x”(包括逗號),然后使用enum語句生成枚舉列表(包括在make_things宏之外的LINEAR_NUM_ITEMS)。 然后創建另一個枚舉,這次將make_thing(x)定義為“FLAG_ENUM _ ## x = 1 <

相當漂亮的一些事情可以通過這種方式完成,旗幟和線性值自動保持同步; 代碼可以做很好的事情,比如“if(thingie [LINEAR_ENUM_foo] thing_errors | = FLAG_ENUM_foo;”(同時使用線性和標志值)。不幸的是,我知道在C#或VB.net中無法做任何遠程類似的事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM