![](/img/trans.png)
[英]Why operators << and >> are not realized for flag enums in C#?
[英]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.