Hello everyone,
I have 3 basic questions about Enum, from MSDN,
http://msdn.microsoft.com/en-us/library/sbbt4032(VS.80).aspx
1.
It is mentioned "A variable of type Days can be assigned any value in the range of the underlying type;" -- I think it is not correct to say any value in the range of the underlying type, like integer, but in the range from Sat to Fri.
For example, you can not write Days d = 65535;
2.
"and if additional elements have been added to the enum type, the test for default values can return true unexpectedly." I do not quite understand this scenario, could anyone show me some code please?
3.
"You can notice these changes when using tools such as the Console class methods, the Expression Evaluator, and so forth. (See example 3).", I have tried example 3. But what are the rules for the changes when we add System.FlagsAttribute? The document only says there will be some changes, but not clearly states what will be the changes. Any ideas?
thanks in advance,
George
George GeorgePosted May 16, 2008, 5:21 AM
Thanks Alan!
Question answered. :-)
regards,
George
AlanPosted May 15, 2008, 11:40 AM
1. Your Days enum looks like this when converted to IL:
.class auto ansi sealed nested private Days
extends [mscorlib]System.Enum
{
.field public static literal valuetype Test/Days Mon = int32(1)
.field public static literal valuetype Test/Days Tue = int32(2)
.field public specialname rtspecialname int32 value__
}
If you have a line like this in C#:
Days d = Days.Mon;
the compiler replaces the constant Days.Mon with its value (i.e. 1) and places this in the memory slot for the variable 'd'. This slot contains the only instance field, value__, and will be 4 bytes long because the underlying type is Int32.
2. Basically, the Flags attribute is of use whenever the ToString() method is called (it's called 'under the hood' in Console.WriteLine() if you don't call it explicitly). This method is inherited from System.Enum where it's overridden to provide the behaviour demonstrated earlier for Flags enums. Apart from that, there are no differences I'm aware of between Flags and ordinary enums.
George GeorgePosted May 14, 2008, 9:59 PM
Thanks Alan,
1.
" a 'static literal' field of the underlying type is created. The value of this constant is the same as its numerical value. So, enums are a bit more than just their underlying types."
I do not quite understand how the internal implementation looks like. Is it like a Dictionary -- string for literal name and int for underlying type's value? Could you show some pseudo code please?
2.
Besides the Console write sample, are there any other differences we could see when using flags or not?
regards,
George
AlanPosted May 14, 2008, 9:55 AM
1. When you declare an enum in C#, the compiler creates a corresponding 'enum class' in IL. This contains an instance field called value__ which holds the current value of the enum. The type of this field is the underlying type of the enum.
In addition, for each of the named constants, a 'static literal' field of the underlying type is created. The value of this constant is the same as its numerical value.
So, enums are a bit more than just their underlying types.
2. How many lions have you heard squeaking ;)
The point is that the writer of the code originally assumed that only the 'Mouse' case would be caught by the default case. Now that an additional element has been added to the enum, the default is being called for Lion as well which is unexpected.
3. If you add these two lines to your Main() method:
Console.WriteLine(Days.Mon | Days.Tue);
Console.WriteLine(DaysFlag.Mon | DaysFlag.Tue);
the first one will print out '3'.
However, the second one will print out 'Mon, Tue' because DaysFlag is a Flags enumeration.
George GeorgePosted May 14, 2008, 8:12 AM
Thanks Alan,
1. So, Enum is just the same as an int treated by IL and CLR internally? :-)
2. When change the code, squeaks is output. Anything wrong?
3. My current confusion is, it seems whether or not using flags attribute has the same result. Here is my code. So, my question now is that I want to see whether there are any special usage for flags attribute which we can not have without this attribute.
Any comments?
[Code]
using System;
class Test
{
enum Days
{
Mon = 1,
Tue = 2
};
[Flags]
enum DaysFlag
{
Mon = 1,
Tue = 2
};
static void Main()
{
int a = (int) (Days.Mon | Days.Tue);
int b = (int)(DaysFlag.Mon | DaysFlag.Tue);
return;
}
}
[/Code]
regards,
George
AlanPosted May 13, 2008, 2:27 PM
1. You can in fact assign any value of the underlying type to an enum as long as you cast it to the enum type first. For example, this works fine:
Days d = (Days)65535;
Console.WriteLine(d);
The last line prints 65535 to the console as there's no named constant corresponding to that value. This feature is of little use in practice except in the case of Flags enums.
2. Consider this simple example:
using System;
enum Animals {Dog, Cat, Mouse}
class Test
{
static void Main()
{
Days d = (Days)65535;
Console.WriteLine(d);
Animals animal = Animals.Mouse;
string action = null;
switch(animal)
{
case Animals.Dog:
action = "barks";
break;
case Animals.Cat:
action = "meows";
break;
default:
action = "squeaks";
break;
}
Console.WriteLine("A {0} {1}", animal.ToString().ToLower(), action);
}
}
Now add 'Lion' to the enum and change this line:
Animals animal = Animals.Mouse;
to this:
Animals animal = Animals.Lion;
3. If you use the Flags attribute and then OR two (or more) enum values together, Console.WriteLine() will show all the values, separated by commas rather than the integral value of the OR'ing operation. So, methods in the Console class are 'Flags' attribute aware.