Fun with enums in C#. Take one generic list that is created to store some Enum that you had defined previously and add few items in it. Iterate with foreach or GetEnumerator<T>() but specify some other enum then the original and see what happens. I was expecting InvalidCastException or something like that but it perfectly works :).    
For the illustration let's take a simple console application and create two enums there: Cars and Animals:
    public enum Cars
    {
        Honda = 0,
        Toyota = 1,
        Chevrolet = 2
    }
    public enum Animals
    {
        Dog = 0,
        Cat = 1,
        Tiger = 2
    }
And do this in main method:
    public static void Main()
    {
        List<Cars> cars = new List<Cars>();
        List<Animals> animals = new List<Animals>();
        cars.Add(Cars.Chevrolet);
        cars.Add(Cars.Honda);
        cars.Add(Cars.Toyota);
        foreach (Animals isItACar in cars)
        {
            Console.WriteLine(isItACar.ToString());
        }
        Console.ReadLine();
    }
It will print this in console:
Tiger Dog Cat
Why is this happening? My first guess was that enum is not actually a Type by himself it's just and int but that's not true: If we write:
Console.WriteLine(Animals.Tiger.GetType().FullName); 
We will get his fully qualified name printed! So why this?
Enum types are distinct, but you're being confused by an implicit cast which is in foreach.
Let's rewrite your loop a bit:
public static void Main()
{
    List<Cars> cars = new List<Cars>();
    List<Animals> animals = new List<Animals>();
    cars.Add(Cars.Chevrolet);
    cars.Add(Cars.Honda);
    cars.Add(Cars.Toyota);
    foreach (Cars value in cars)
    {
        // This time the cast is explicit.
        Animals isItACar = (Animals) value;
        Console.WriteLine(isItACar.ToString());
    }
    Console.ReadLine();
}
Now does the result surprise you? Hopefully not, except possibly the fact that you can cast from one enum to another. This is just a more explicit version of what your original code is doing.
The fact that there's a cast implicit in every foreach loop (even though it's usually a no-op) is the bit which most developers would find confusing, I think.
From section 8.8.4 of the C# 3.0 spec:
The above steps, if successful, unambiguously produce a collection type C, enumerator type E and element type T. A foreach statement of the form
foreach (V v in x)  embedded-statement 
is then expanded to:
{
    E e = ((C)(x)).GetEnumerator();
    try {
        V v;
        while (e.MoveNext()) {
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        ... // Dispose e
    }
}
The enumeration conversion itself is covered in section 6.2.2:
The explicit enumeration conversions are:
An explicit enumeration conversion between two types is processed by treating any participating enum-type as the underlying type of that enum-type, and then performing an implicit or explicit numeric conversion between the resulting types. For example, given an enum-type E with and underlying type of int, a conversion from E to byte is processed as an explicit numeric conversion (§6.2.1) from int to byte, and a conversion from byte to E is processed as an implicit numeric conversion (§6.1.2) from byte to int.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With