What does George Boole have to do with whether or not an undefined enum can exist?
Oh not terribly much
, He's just the guy that came up with the entire concept of using a single numeric integral value to represent multiple true/false states, which is what an Enum with the [Flags] attributes represents.
//
//there are no enum values in the definition that equate to 0,3,5,7,9,11,13 or 15
//they are achieved through bitwise operations
[Flags]
public enum MyEnum
{
read = 1,
write = 2,
create = 4,
delete = 8
}
Let me try this:
Are enums essentially integers that we can assign any arbitrary but valid value to, even if it isn't defined at designtime? Or are we basically saying when we declare enums that *thesevariables* equal *thesevalues* and MyEnum someVal = 15 is just as valid as (if not more appropriate than) this:
//
//rwcd = 15 is redundant and unnecessary
//
[Flags]
public enum MyEnum
{
read = 1,
write = 2,
create = 4,
delete = 8,
rwcd = 15
}
The problem is that you're expressing the logical 'or' of multiple Enum fields as a literal integer, which is technically-considered a no-no (see below).
As far as the 'rwcd' enum member, yes you can define that if you want, as a convenience that avoids having to logically-combine the component fields using the | (or) operator, and as a way of ensuring that existing code is not broken as it would be if you were to express the logical combination of several members as a literal integer (see below).
Here is an example from my post showing how to use the MatchProperties protocol extension, that also defines a 'synonym' (MathPropFlags.Entity) that is the logical combination of several other members. Notice that the Entity member's value is not expressed as a literal integer, but rather by using the logical 'or' (|) operator to logically-combine the members it acts as a synonym for, which is important:
[Flags]
public enum MatchPropFlags
{
Color = 0x1,
Layer = 0x2,
Linetype = 0x4,
Thickness = 0x8,
LinetypeScale = 0x10,
Text = 0x20,
Dimension = 0x40,
Hatching = 0x80,
Lineweight = 0x100,
PlotStyleName = 0x200,
Polyline = 0x400,
Viewport = 0x800,
Table = 0x1000,
Material = 0x2000,
ShadowDisplay = 0x4000,
Multileader = 0x8000,
All = 0xFFFF,
Entity = Color | Layer | Linetype | Thickness
| LinetypeScale | Material | Lineweight
| PlotStyleName | ShadowDisplay
};
Notice that the last element is actually a logical combination of all of the elements shown between the | (or) operators, and that serves two purposes. It is a convenience to avoid having to express the combined elements literally each time that value is used, and it also insulates the code that uses the 'Entity' member from future changes that may occur (a perfect example being that in a later AutoCAD release, the Transparency flag was added to the Entity member, so any existing code that runs on supported releases will automatically support matching an entity's Transparency property, if it used the 'Entity' member, verses explicitly specifying all of its components individually).
In code you wouldn't express it as an integer because that elminates one of the main advantages that using an enum has, which is that you can change its definition without having to find every (incorrect) use of an integer that expresses multiple bits.
In other words, instead of saying:
[Flags]
public enum MyEnum
{
read = 1,
write = 2,
create = 4,
delete = 8,
rwcd
= 15 <<< this is a no
-no
}
You are supposed to express it thusly in code:
[Flags]
public enum MyEnum
{
read = 1,
write = 2,
create = 4,
delete = 8,
rwcd = read | write | create | delete
}
So, the bitwise '|' ("Or") operator logically-combines the values of two or more members of the enum in a way that does not create a dependence on their exact values, which would allow you to change the definition of the Enum after the fact, without breaking any existing code that uses the enum members (as opposed to using integers).
Similarly, you should never express the logical-combination of multiple enum members literally as an integer anywhere in code, because that creates a dependence on the actual value at the time the code was written, and would be broken if you were to modify the enum's definition after the fact.
Yes, an enum is just compiler sugar for an ordinal type (it could be a short, integer, or long, which you can define yourself using the : operator). In the compiled code it ends up as a number.
Incidently, I have finished coding the class in which this is used. I ended up with 17 different enums (I was able to reduce it from 23) and 174 values in those 17 enums. All told there are over 200 permissions that this will be used to manage.
Great. The most interesting part is in how you connect enum values to UI elements like check boxes (using Data binding and custom type descriptors).
I don't have a shareable example of that handy, but in short, I can data bind the Checked property of a checkbox to a property of an Enum type, and specify the Enum member that the checkbox controls, without having to write any code.