In c# it is quite common to find the following Enum structure
[Flags]
public enum Permission
{
Read = 1 << 1,
Create = 1 << 2,
Update = 1 << 3,
Destroy = 1 << 4
}
which allows you to join enums like this: Permission.Read|Permission.Create
I am now faced with a different sort of requirement, and the solutions I have come up with are problematic IMO.
I need to allow some sort of enum implementation to multiple types of premissions - some contradicting, and some aren't
and I want the following sort of functionality
[Flags]
public enum Permission
{
Read1 = 1,
Read2 = 2,
Read3 = 3,
Write1 = 10,
Write2 = 20,
Write3 = 30,
Update1 = 100,
Update2 = 200,
Update3 = 300,
Destory = 1000,
Other = 10000,
SomethingElse = 100000,
}
when this won't work Permission.Read1|Permission.Read2 mainly because it means a user now has a reading permission level 3
besides using different bit flag for each Permission (which will require my db to hold a much larger integer than a INT for a very bad reason), or having a different enum (and column) per permission (which will limit my flexibility with the permissions) , and having no form of compile time verification (I guess I can create some sort of a workarroundish runtime verification) do you have any other idea?
Your db doesn't need to store bigger than int. 32bits can accommodate lot more values for unique bit flags. Following hex values are unique binary bit flags. Read1 | Read2 won't equal Read3
[Flags]
public enum Permission
{
Read1 = 0x00000001,
Read2 = 0x00000002,
Read3 = 0x00000004,
Write1 = 0x00000008,
Write2 = 0x00000010,
Write3 = 0x00000020,
Update1 = 0x00000040,
Update2 = 0x00000080,
Update3 = 0x00000100,
Destory = 0x00000400,
Other = 0x00000800,
SomethingElse = 0x00001000,
}
You can probably organize these better by blocking certain bit blocks as Read, Write etc. E.g. you can block Read to be blocked for first 8 bits, write for next 8 bits so on and so forth. That way, you can accommodate future changes and also use bit masking effectively.
Related
I have an enumeration with flags. I want to declare a variable with n different flags. n > 1 in this case.
public enum BiomeType {
Warm = 1,
Hot = 2,
Cold = 4,
Intermediate = 8,
Dry = 16,
Moist = 32,
Wet = 64,
}
Okay - one variant is to cast each flag into an byte and cast the result to my enum.
BiomeType bType = (BiomeType)((byte)BiomeType.Hot + (byte)BiomeType.Dry)
But this is kinda messy - imho. Is there an more readable way to combine flags?
Simple, use the binary "or" operator:
BiomeType bType = BiomeType.Hot | BiomeType.Dry;
Also, if the values can be combined like this it's best to mark the enum with the Flags attribute to indicate this:
[Flags]
public enum BiomeType {
Warm = 1,
Hot = 2,
Cold = 4,
Intermediate = 8,
Dry = 16,
Moist = 32,
Wet = 64,
}
Adding enumeration values is bad for a number of reasons. It makes it easy to produce a value that is outside the defined values, i.e.:
BiomeType bType = (BiomeType)((byte)BiomeType.Wet + (byte)BiomeType.Wet);
While contrived, this example yields a value of 128, which doesn't map to a known value. This will still compile and run, but it's likely you didn't build your code to handle values outside of those defined and could lead to undefined behavior. However, if you use the pipe (or "binary or") operator:
BiomeType bType = BiomeType.Wet | BiomeType.Wet;
The result is still just BiomeType.Wet.
Furthermore, using addition like in your question provides no Intellisense in the IDE which makes using the enumeration unnecessarily more difficult.
Add the [Flags] attribute to your enum. Then you can just mask them:
[Flags]
public enum BiomeType
{
Warm = 1,
Hot = 2,
Cold = 4,
Intermediate = 8,
Dry = 16,
Moist = 32,
Wet = 64,
}
BiomeType bType = BiomeType.Hot | BiomeType.Dry;
(Actually you can mask then without the flags attribute, but you should add it for clarity.)
You can even do something like this to combine all the flags:
var allBiomeTypes = ((BiomeType[])Enum.GetValues(typeof(BiomeType))).Aggregate((BiomeType)0, (a, c) => a | c);
Use the | (bitwise or) operator. You get IntelliSense support for this. (The other bitwise operators function the same as they do on the underlying numeric type.)
var bType = BiomeType.Hot | BiomeType.Dry;
You should also use the [Flags] attribute as a hint on the enum definition:
[Flags]
public enum BiomeType
{
Warm = 1,
Hot = 2,
Cold = 4,
Intermediate = 8,
Dry = 16,
Moist = 32,
Wet = 64,
}
(For an explanation, see What does the [Flags] Enum Attribute mean in C#?)
Let's say I have following code:
[Flags]
enum MyFlags
{
None = 0,
A = 1,
B = 2,
C = 4,
D = 8,
E = 16,
// ...
}
This is obviously not going to be optimal when the amount of flags grow very large. And by optimal, mean readable, not fast or memory saving.
For combined flags, such as
AB = 3
we can easily use
AB = A | B
instead, which is more readable.
And for combining all flags
All = A | B | C | ...
it would be more favorable to use
All = ~None
instead, even if we don't make full use of all 32/64 bits available.
But what about regular values?
Between
E = 16
E = 0b10000
E = 0x10
E = 1 << 4
or other ways I haven't thought of, which would be best suited for a large amount of flags?
Or in other words, what is the (agreed upon) convention for setting values for flags in C#?
Let us assume for the sake of argument, that the values will not be aligned, so the code might very well look like this
None = 0,
Apple = 1,
Banana = 2,
StrangeFruit = Apple | Banana,
Cherry = 4,
Date = 8,
Elderberry = 16,
// ...
For regular values, I like 1 << n: after you've taken the (short) time to understand it, it's very easy to see what's going on, hard to mess up, and requires no hex/binary conversion/thinking.
[Flags]
enum MyFlags
{
None = 0,
A = 1 << 0,
B = 1 << 1,
C = 1 << 2,
D = 1 << 3,
E = 1 << 4,
// ...
Lastly = 1 << 31,
}
As far as an actual defined convention, I don't think one exists. MS's Enum Design guidelines says
√ DO use powers of two for the flag enum values so they can be freely combined using the bitwise OR operation.
but does not specify how to write this in your source (those are language-agnostic guidelines; what might be good in C# might not even work in another .Net language).
I don't think there's any established convention. You might consult Framework Design Guidelines by Cwalina, Abrahms for guidance.
I prefer to use the hex method 0x00, 0x01. You use 1, 2, 4, 8, and then move left to the next position. For values that are commonly combined, I prefer the OR'ing method you describe.
Example:
[Flags]
public enum Directions
{
None = 0x00,
Left = 0x01,
Right = 0x02,
Top = 0x04,
Bottom = 0x08,
Forward = 0x10,
Backward = 0x20,
TopLeft = Top | Left,
TopRight = Top | Right,
BottomLeft = Bottom | Left,
BottomRight = Bottom | Right
}
I have a subsystem of a peripherals hardwares. Each peripheral can return few errors
The sub system indicates each error in a flag so when I call a method to check all the peripheral status it returns me a Uint64 code, which is a sum of all of the error codes
example
error1 = 1;
error2 = 2;
error3 = 4;
......
error7 = 64;
error8 = 128;
error9 = 256;
.......
so if i get a return code of 196 it mean i got error3,error8 and error 7 (4+64+128)
the number of total error can reach more than 50 errors and that's why the return code is Uint64
which the error64 can be a very large number(18446744073709551616), and can have more then 80 error in future reference
Is there a way to implement flag system when are more then 50 flags to check?
I will try to give a mechanism for storing more than 64 errors with a Uint64 Enum.
public enum MyFlag : UInt64
{
control = 1,
error1 = 2,
error2 = 4,
error3 = 8,
//.......
error63 = 9223372036854775808
}
This is the enum. Observe that we reserve the least significant bit for a control bit.
This means we can now have 63*2 = 126 different codes.
The drawback is that instead of the usual check, for instance:
resultFlag & MyFlag.error3
we will need to make a composite check, like:
resultFlag & MyFlag.error3 && resultFlag & MyFlag.control
or:
resultFlag & MyFlag.error3 && resultFlag%2
I hope this helps. Cheers.
you can create enum:
[Flags] enum Errors {error1 =1,error2=2,error3=4, error4=8}
and then when you get answer from your subsystem just do that.
var MyNewError = 11;
Errors DecodedErrors = (Errors)MyNewError;
and then you will get fast list of all errors by converting DecodedErrors to string.
Console.WriteLine(DecodedErrors.ToString());
//output: error1, error2, error4
Combine it with #nestedloop solution and you are in home.
I have the enum:
[Flags]
enum Editions
{
Educational,
Basic,
Pro,
Ultra
}
why do I get this behavior?
var x = Editions.Basic;
var y = Editions.Educational;
var test =x.HasFlag(y); // why is this true!?
// and!!!
var test2 = y.HasFlag(x); // this is false!
When using the [Flags] attribute you should explicitly map the enum values to integer that contain non overlapping bit patterns. That is, each enum value should be mapped to a power of two:
[Flags]
enum Editions
{
Educational = 1,
Basic = 2,
Pro = 4,
Ultra = 8
}
Without the explicit numbering, Educational will be mapped to 0 and Basic to 1.
Enum.HasFlags checks if the bit field or bit fields that are set in the parameter are also all set in the tested enum. In your case, x is 1 and y is 0. That means that x contains all of the bits set in 0 (that is no bits at all). However 0 does not contain the bits set in 1 when testing the other way around.
It returns true because you implemented Editions incorrectly. You must explicitly set the values when you use the [Flags] attribute.
[Flags]
enum Editions
{ //binary format
Educational = 1 << 0, // 0001
Basic = 1 << 1, // 0010
Pro = 1 << 2, // 0100
Ultra = 1 << 3 // 1000
}
If you do not assign numbers it will auto assign them starting at 0 going up by 1 for each option after that (this is standard enum behavior, adding the [Flags] attribute does not change this behavior)
[Flags]
enum Editions
{ //binary format
Educational = 0, // 0000
Basic = 1, // 0001
Pro = 2, // 0010
Ultra = 3 // 0011
}
So the two tests you did was: 0001 has the flag 0000 set (which is true, you are not testing for any flags) and 0000 has the flag 0001 set (which is defiantly false)
However looking at your names I doubt you should be using [Flags] at all because I doubt whatever you are doing can be Basic and be Pro at the same time. If you are trying to use flags to make testing enum values easier just use a switch statement instead
Editions edition = GetEdition();
switch(edition)
{
case Editions.Basic:
DoSomthingSpecialForBasic();
break;
case Editions.Pro:
case Editions.Ultra:
DoSomthingSpecialForProAndUltra();
break;
//Does not do anything if Editions.Educational
}
Why are people always using enum values like 0, 1, 2, 4, 8 and not 0, 1, 2, 3, 4?
Has this something to do with bit operations, etc.?
I would really appreciate a small sample snippet on how this is used correctly :)
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
Because they are powers of two and I can do this:
var permissions = Permissions.Read | Permissions.Write;
And perhaps later...
if( (permissions & Permissions.Write) == Permissions.Write )
{
// we have write access
}
It is a bit field, where each set bit corresponds to some permission (or whatever the enumerated value logically corresponds to). If these were defined as 1, 2, 3, ... you would not be able to use bitwise operators in this fashion and get meaningful results. To delve deeper...
Permissions.Read == 1 == 00000001
Permissions.Write == 2 == 00000010
Permissions.Delete == 4 == 00000100
Notice a pattern here? Now if we take my original example, i.e.,
var permissions = Permissions.Read | Permissions.Write;
Then...
permissions == 00000011
See? Both the Read and Write bits are set, and I can check that independently (Also notice that the Delete bit is not set and therefore this value does not convey permission to delete).
It allows one to store multiple flags in a single field of bits.
If it is still not clear from the other answers, think about it like this:
[Flags]
public enum Permissions
{
None = 0,
Read = 1,
Write = 2,
Delete = 4
}
is just a shorter way to write:
public enum Permissions
{
DeleteNoWriteNoReadNo = 0, // None
DeleteNoWriteNoReadYes = 1, // Read
DeleteNoWriteYesReadNo = 2, // Write
DeleteNoWriteYesReadYes = 3, // Read + Write
DeleteYesWriteNoReadNo = 4, // Delete
DeleteYesWriteNoReadYes = 5, // Read + Delete
DeleteYesWriteYesReadNo = 6, // Write + Delete
DeleteYesWriteYesReadYes = 7, // Read + Write + Delete
}
There are eight possibilities but you can represent them as combinations of only four members. If there were sixteen possibilities then you could represent them as combinations of only five members. If there were four billion possibilities then you could represent them as combinations of only 33 members! It is obviously far better to have only 33 members, each (except zero) a power of two, than to try to name four billion items in an enum.
Because these values represent unique bit locations in binary:
1 == binary 00000001
2 == binary 00000010
4 == binary 00000100
etc., so
1 | 2 == binary 00000011
EDIT:
3 == binary 00000011
3 in binary is represented by a value of 1 in both the ones place and the twos place. It is actually the same as the value 1 | 2. So when you are trying to use the binary places as flags to represent some state, 3 isn't usually meaningful (unless there is a logical value that actually is the combination of the two)
For further clarification, you might want to extend your example enum as follows:
[Flags]
public Enum Permissions
{
None = 0, // Binary 0000000
Read = 1, // Binary 0000001
Write = 2, // Binary 0000010
Delete = 4, // Binary 0000100
All = 7, // Binary 0000111
}
Therefore in I have Permissions.All, I also implicitly have Permissions.Read, Permissions.Write, and Permissions.Delete
[Flags]
public Enum Permissions
{
None = 0; //0000000
Read = 1; //0000001
Write = 1<<1; //0000010
Delete = 1<<2; //0000100
Blah1 = 1<<3; //0001000
Blah2 = 1<<4; //0010000
}
I think writing using a binary shift operator << is easier to understand and read, and you don't need to calculate it.
These are used to represent bit flags which allows combinations of enum values. I think it's clearer if you write the values in hex notation
[Flags]
public Enum Permissions
{
None = 0x00,
Read = 0x01,
Write = 0x02,
Delete= 0x04,
Blah1 = 0x08,
Blah2 = 0x10
}
This is really more of a comment, but since that wouldn't support formatting, I just wanted to include a method I've employed for setting up flag enumerations:
[Flags]
public enum FlagTest
{
None = 0,
Read = 1,
Write = Read * 2,
Delete = Write * 2,
ReadWrite = Read|Write
}
I find this approach especially helpful during development in the case where you like to maintain your flags in alphabetical order. If you determine you need to add a new flag value, you can just insert it alphabetically and the only value you have to change is the one it now precedes.
Note, however, that once a solution is published to any production system (especially if the enum is exposed without a tight coupling, such as over a web service), then it is highly advisable against changing any existing value within the enum.
Lot's of good answers to this one… I'll just say.. if you do not like, or cannot easily grasp what the << syntax is trying to express.. I personally prefer an alternative (and dare I say, straightforward enum declaration style)…
typedef NS_OPTIONS(NSUInteger, Align) {
AlignLeft = 00000001,
AlignRight = 00000010,
AlignTop = 00000100,
AlignBottom = 00001000,
AlignTopLeft = 00000101,
AlignTopRight = 00000110,
AlignBottomLeft = 00001001,
AlignBottomRight = 00001010
};
NSLog(#"%ld == %ld", AlignLeft | AlignBottom, AlignBottomLeft);
LOG 513 == 513
So much easier (for myself, at least) to comprehend. Line up the ones… describe the result you desire, get the result you WANT.. No "calculations" necessary.