Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

foreach(Derived obj in new List<Base>())

What does the following code do?

class Base { }
class Derived : Base { }
class Test
{
    void Foo(List<Base> list)
    {
        foreach (Derived obj in list)
        {
            // ...
        }
    }
}

I didn't expect it to even compile, but it does.

like image 646
Stefan Monov Avatar asked Oct 12 '10 16:10

Stefan Monov


2 Answers

The behavior you are observing is according to section 8.8.4 The foreach statement of the C# language specification. This section defines the semantics of the foreach statement as follows:

[...] 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()) {
            // here the current item will be casted                
            v = (V)(T)e.Current;
            embedded-statement
        }
    }
    finally {
        // Dispose e
    }
}

The reason that the compiler inserts this explicit cast is historic. C# 1.0 didn't have generics so in order to allow simple code like this

ArrayList list = new ArrayList();
list.Add(1);
foreach (int i in list)
{
   ...
}

it was decided to let the compiler introduce the cast.

like image 82
Dirk Vollmar Avatar answered Sep 19 '22 22:09

Dirk Vollmar


Absolutely nothing, but it does it in a very inefficient manner.

The order of operations is this:

  1. Instantiate a new List, with zero items
  2. Iterate over that newly instantiated list, which has zero items
  3. Not cast the Base object to a Derived object, because the list has zero items. If the list had any items, this step would result in a runtime exception.
  4. Not execute the code in the foreach block, because the list has zero items.

Edit
Based on your edit, you run the risk of an InvalidCastException should any element of the list passed to Foo not actually be a Derived object.

Edit2
Why does it compile? Because foreach involves an implicit cast to Object for each item in the list, then another explicit cast to the specified type in the foreach block, in this case Derived

like image 45
Randolpho Avatar answered Sep 19 '22 22:09

Randolpho