Question about enum values

A

Author

I am studying Scott Allen's Workflow sample code for an order
processing application. Below is an enum he defines:

[Flags]
public enum OrderTransitions
{
None = 0,
CanOpen = 1,
CanProcess = 2,
CanComplete = 4,
CanCancel = 8
}

I am curious about the int values he assigned to the enum. There must
be a reason that he wants to use values that are 2^n instead of using
0, 1, 2, 3, 4.

Any hint? Thanks a lot.
 
J

Jeroen Mostert

Author said:
I am studying Scott Allen's Workflow sample code for an order
processing application. Below is an enum he defines:

[Flags]
public enum OrderTransitions
{
None = 0,
CanOpen = 1,
CanProcess = 2,
CanComplete = 4,
CanCancel = 8
}

I am curious about the int values he assigned to the enum. There must
be a reason that he wants to use values that are 2^n instead of using
0, 1, 2, 3, 4.
The reason is the [Flags] attribute, which allows you to combine values:

OrderTransitions canCompleteAndCancel = OrderTransitions.CanComplete |
OrderTransitions.CanCancel;

Obviously this only really makes sense if the values are bitwise distinct.
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.
 
A

Author

Author said:
I am studying Scott Allen's Workflow sample code for an order
processing application.  Below is an enum he defines:
[Flags]
public enum OrderTransitions
{
        None        = 0,
        CanOpen     = 1,
        CanProcess  = 2,
        CanComplete = 4,
        CanCancel   = 8
}
I am curious about the int values he assigned to the enum.  There must
be a reason that he wants to use values that are 2^n  instead of using
0, 1, 2, 3, 4.

The reason is the [Flags] attribute, which allows you to combine values:

   OrderTransitions canCompleteAndCancel = OrderTransitions.CanComplete |
OrderTransitions.CanCancel;

Obviously this only really makes sense if the values are bitwise distinct..
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.

Thanks. I don't quite understand.

So, let's say, like what you said, we have this:

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
8, 1000, CanCancel

or

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
4, 0100, CanCancel

In the first case, CanComplete | CanCancel gives us 1011 and CanOpen |
CanProcess gives us 0011

In the second case, CanComplete | CanCancel gives us 0111, and CanOpen
| CanProcess gives us 0011

Of course, in the second case, None | CanComplete and CanOpen |
CanProcess will give us the same result: 0011
 
J

Jeff Dillon

So, let's say, like what you said, we have this:

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
8, 1000, CanCancel

or

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
4, 0100, CanCancel

In the first case, CanComplete | CanCancel gives us 1011 and CanOpen |
CanProcess gives us 0011

In the second case, CanComplete | CanCancel gives us 0111, and CanOpen
| CanProcess gives us 0011

Of course, in the second case, None | CanComplete and CanOpen |
CanProcess will give us the same result: 0011
 
J

Jeroen Mostert

Author said:
Author said:
I am studying Scott Allen's Workflow sample code for an order
processing application. Below is an enum he defines:
[Flags]
public enum OrderTransitions
{
None = 0,
CanOpen = 1,
CanProcess = 2,
CanComplete = 4,
CanCancel = 8
}
I am curious about the int values he assigned to the enum. There must
be a reason that he wants to use values that are 2^n instead of using
0, 1, 2, 3, 4.
The reason is the [Flags] attribute, which allows you to combine values:

OrderTransitions canCompleteAndCancel = OrderTransitions.CanComplete |
OrderTransitions.CanCancel;

Obviously this only really makes sense if the values are bitwise distinct.
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.
Thanks. I don't quite understand.
There's documentation: http://msdn.microsoft.com/library/system.enum
So, let's say, like what you said, we have this:

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
8, 1000, CanCancel

or

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
4, 0100, CanCancel
Note that neither of these is correct for defining an enum that uses flags,
as the values overlap.
In the first case, CanComplete | CanCancel gives us 1011 and CanOpen |
CanProcess gives us 0011
Yes, but what I meant was that CanProcess | CanOpen == CanComplete. This is
not what we want, since CanComplete should be a distinct flag.
In the second case, CanComplete | CanCancel gives us 0111, and CanOpen
| CanProcess gives us 0011

Of course, in the second case, None | CanComplete and CanOpen |
CanProcess will give us the same result: 0011
"None" is a special value that should not be used in expressions like these;
it simply indicates that all flags are off.
 
A

Author

So, let's say, like what you said, we have this:

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
8, 1000, CanCancel

or

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
4, 0100, CanCancel

In the first case, CanComplete | CanCancel gives us 1011 and CanOpen |
CanProcess gives us 0011

In the second case, CanComplete | CanCancel gives us 0111, and CanOpen
| CanProcess gives us 0011

Of course, in the second case, None | CanComplete and CanOpen |
CanProcess will give us the same result: 0011

Yeah, I know Scott Allen's original (i.e., CanComplete = 4 instead of
3) would work like Jeroen said.

But, Jeroen says:

<quote>
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.
</quote>

So, I don't know if he wants CanCancel to be 4 or 8. That's why I had
two cases, 0, 1, 2, 3, 8 and 0, 1, 2, 3, 4. I did not need to test 0,
1, 2, 4, 8, which I know how it works after Jeroen's explanation.
 
A

Author

Author said:
Author wrote:
I am studying Scott Allen's Workflow sample code for an order
processing application.  Below is an enum he defines:
[Flags]
public enum OrderTransitions
{
        None        = 0,
        CanOpen     = 1,
        CanProcess  = 2,
        CanComplete = 4,
        CanCancel   = 8
}
I am curious about the int values he assigned to the enum.  There must
be a reason that he wants to use values that are 2^n  instead of using
0, 1, 2, 3, 4.
The reason is the [Flags] attribute, which allows you to combine values:
   OrderTransitions canCompleteAndCancel = OrderTransitions.CanComplete |
OrderTransitions.CanCancel;
Obviously this only really makes sense if the values are bitwise distinct.
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.
Thanks.  I don't quite understand.

There's documentation:http://msdn.microsoft.com/library/system.enum


So, let's say, like what you said, we have this:
0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
8, 1000, CanCancel

0, 0000, None
1, 0001, CanOpen
2, 0010, CanProcess
3, 0011, CanComplete
4, 0100, CanCancel

Note that neither of these is correct for defining an enum that uses flags,
as the values overlap.
In the first case, CanComplete | CanCancel gives us 1011 and CanOpen |
CanProcess gives us 0011

Yes, but what I meant was that CanProcess | CanOpen == CanComplete. This is
not what we want, since CanComplete should be a distinct flag.

OK, now that clears my confusion. Thanks a lot.
 
J

Jeroen Mostert

Author said:
Yeah, I know Scott Allen's original (i.e., CanComplete = 4 instead of
3) would work like Jeroen said.

But, Jeroen says:

<quote>
If "CanComplete" was defined as 3, it would look the same as CanOpen |
CanProcess.
</quote>

So, I don't know if he wants CanCancel to be 4 or 8.

I... really don't want it to be anything. Pretend it doesn't exist. It's
orthogonal to my point. If the flags are already incorrect it doesn't matter
how you continue.
That's why I had
two cases, 0, 1, 2, 3, 8 and 0, 1, 2, 3, 4. I did not need to test 0,
1, 2, 4, 8, which I know how it works after Jeroen's explanation.
Yes, let's focus on that and forget the rest. 0, 1, 2, 4, 8 etcetera is the
only correct progression for bitflags.
 
A

Author

I... really don't want it to be anything. Pretend it doesn't exist. It's
orthogonal to my point. If the flags are already incorrect it doesn't matter
how you continue.


Yes, let's focus on that and forget the rest. 0, 1, 2, 4, 8 etcetera is the
only correct progression for bitflags.

I understood, I was only testing how we get

OrderTransitions canCompleteAndCancel = OrderTransitions.CanComplete |
OrderTransitions.CanCancel;

should we assign 0, 1, 2, 3, 4 or 0, 1, 2, 3, 8.

I guess it is my turn to confuse you now. :)
 
B

Bob Milton

This is a trick that has been around for at least 50 years (when I first
learned it). If my distinct flags are powers of two, I can combine those
with a bitwise or to get a value that is different than any of the
individual flags. AND, I can test any combination to see if a specific flag
by simpy doing a bitwese and. So CanProcess | CanComplete is 6, and is
distinct from any enum value. If I set a=6 and I want to know if the
CanProcess flag is set, I simply do a & CanProcess. That will give me zero
(or LOGICAL false) if that flag is not set, and non-zero (or LOGICAL true)
if the flag is set. All done with bitwise operators which tend to be the
fastest operations a computer can do.
I'm sure you will find this in one of the Donald Knuth volumes.
Bob
 
P

Peter Webb

I... really don't want it to be anything. Pretend it doesn't exist. It's
orthogonal to my point. If the flags are already incorrect it doesn't
matter how you continue.

I would have thought that the underlying vectors being orthogonal was your
point !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top