标签云

微信群

扫码加入我们

WeChat QR Code

From time to time I see an enum like the following:[Flags]public enum Options {None= 0,Option1 = 1,Option2 = 2,Option3 = 4,Option4 = 8}I don't understand what exactly the [Flags]-attribute does.Anyone have a good explanation or example they could post?


It's also worth noting, in addition to the accepted answer, that VB.NET actually requires [Flags] - at least according to the .NET guys: social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/…

2019年10月20日35分43秒

Note, not required in VB these days.Save behaviour as C# - just changes the ToString() output.Note, you can also do logical OR, WITHIN the Enum itself. Very cool.Cat = 1, Dog = 2, CatAndDog = Cat || Dog.

2019年10月20日35分43秒

Chalky You mean CatAndDog = Cat | Dog (the logical OR instead of the Conditional), I assume?

2019年10月20日35分43秒

DdW, partially correct: | should be used, but | is called the binary OR. II is the logical OR (that allows short-circuiting): At least according to Microsoft ;) msdn.microsoft.com/en-us/library/f355wky8.aspx

2019年10月20日35分43秒

Flags itself does nothing. Also, C# does not require Flags per se. But the ToString implementation of your enum uses Flags, and so does Enum.IsDefined, Enum.Parse, etc. Try to remove Flags and look at the result of MyColor.Yellow | MyColor.Red; without it you get "5", with Flags you get "Yellow, Red". Some other parts of the framework also use [Flags] (e.g., XML Serialization).

2019年10月20日35分43秒

// Yellow has been set..., I find a bit misleading. Nothing has beenset, it means that Yellow is a member of your AllowedColors, perhaps better wouldbe //Yellowisallowed ?

2019年10月21日35分43秒

I prefer to use constants of the form A = 1 << 0, B = 1 << 1, C = 1 << 2 ... Much easier to read, understand, visually check and change.

2019年10月20日35分43秒

borrrden, hell yeahh! I found this: msdn.microsoft.com/en-us/library/system.enum.aspx - see "Remarks" part: "Enum is the base class for all enumerations in the .NET Framework." and "The enumeration does not explicitly inherit from Enum; the inheritance relationship is handled implicitly by the compiler." So, when you write: public enum bla bla bla - this is a value type. But, the HasFlag method wants you to give him an instance of System.Enum which is a class (reference type:)

2019年10月20日35分43秒

Enum.IsDefined does not take the FlagsAttribute into account. None of the following return true, even with the attribute: Yellow | Green, "Yellow, Green", 3

2019年10月20日35分43秒

That's what I mean, I prefer to have the full int in source code. If I have a column on a table in the database called MyEnum that stores a value of one of the enums, and a record has 131,072, I would need to get out my calculator to figure out that that corresponds to the enum with the value 1<<17. As opposed to just seeing the value 131,072 written in the source.

2019年10月20日35分43秒

jwg I agree, it's silly to be overly worried about the runtime performance of this, but all the same, I do think its nice to know that this isn't going to be inserting bitshifts anywhere you use the enum. More of a 'that's neat' thing rather than anything related to performance

2019年10月20日35分43秒

JeremyWeir - Several bits are going to be set in a flag enumeration value. So your method of data analysis is what is improper. Run a procedure to Represent your integer value in binary. 131,072 [D] = 0000 0000 0000 0001 0000 0000 0000 0000 [B] [32].. With the 17th bit set, an enum value assigned 1<<17 is easily determinable. 0110 0011 0011 0101 0101 0011 0101 1011 [b] [32] .. the enum values assign 1<<31, 1<<30, 1<<26, 1<<25.. etc. etc. is determinable without even the aid of a calculator at all.. which I doubt you would be able to determine at all without getting the binary rep.

2019年10月20日35分43秒

Also pointing out you can bit-shift from "previous" enum values rather than directly from numbers, i.e. Third = Second << 1 rather than Third = 1 << 2 -- see more complete description below

2019年10月20日35分43秒

I like this, but once you get to the upper limits of the underlying enum type, the compiler doesn't warn against bit shifts such as 1 << 31 == -2147483648, 1 << 32 == 1, 1 << 33 == 2, and so on.By contrast, if you say ThirtySecond = 2147483648 for an int type enum, the compiler throws an error.

2019年10月20日35分43秒

The combinations are a good recommendation, but I think the chained bit-shift would be prone to copy-and-paste errors such as Two = One << 1, Three = One << 1, etc... The incrementing integers of the form 1 << n are safer and the intent is clearer.

2019年10月20日35分43秒

RupertRawnsley to quote my answer: > Not necessarily recommending it, but just pointing out you can

2019年10月20日35分43秒

This example works even if you leave out [Flags].It's the [Flags] part I'm trying to learn about.

2019年10月20日35分43秒

IsSet is an extension method I assume?

2019年10月20日35分43秒

Yeah - read the other question that I link to for details: stackoverflow.com/questions/7244

2019年10月20日35分43秒

.NET 4 adds a HasFlag method to enumerations, so you can do opt.HasFlag( PossibleOptions.OptionOne ) without having to write your own extensions

2019年10月20日35分43秒

Note that HasFlag is much slower than doing bitwise operations.

2019年10月20日35分43秒

WaiHaLee You can use CodeJam.EnumHelper.IsFlagSet extension method which is compiled to a fast version using Expression: github.com/rsdn/CodeJam/wiki/M_CodeJam_EnumHelper_IsFlagSet__1

2019年10月20日35分43秒

or Mode |= Mode.Write

2019年10月20日35分43秒

Enum may be based on a signed type, so you should use "!= 0" instead of ">0".

2019年10月20日35分43秒

JaimePardos -- As long as we keep them honest bytes, as I do in this example, there's no concept of negative. Just 0 to 255. As MSDN warns, "Use caution if you define a negative number as a flag enumerated constant because... [that] might make your code confusing and encourage coding errors." It's strange to think in terms of "negative bitflags"! ;^) I'll edit more in a bit. But you're right, if we do use negative values in our enum, we'd need to check for != 0.

2019年10月20日35分43秒