2

As I mentioned in this post, I faced a for me not understandable compiler behaviour.

The code:

IEnumerable<IList<MyClass>> myData = //...getMyData
foreach (MyClass o in myData){}

It compiles, but fails on runtime: InvalidCastException; for me it is obvious.

If I change the IList to List as following, it complains:

IEnumerable<List<MyClass>> myData = //...getMyData
foreach (MyClass o in myData){}

When instead of the class type I put var as following, intellisense recognizes the correct type:

IEnumerable<List<MyClass>> myData = //...getMyData
foreach (var o in myData){}

My first question was: Why doesn't the compiler complain? The answer was that the behaviour respects the C# Language definition. See chapter 6.2.4 Explicit reference conversions, page 116.

Read the 4th and 5th statement:

• From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.

• From any interface-type S to any interface-type T, provided S is not derived from T.

For the second part of the first statement provided T implements S is clear, no doubts.
But why might we cast an interface-type S to any class-type T if it is not derived or not implemented?
In which case/scenario with an non empty list would the code run without throwing an InvalidCastException?

Community
  • 1
  • 1
Emaborsa
  • 2,360
  • 4
  • 28
  • 50
  • 2
    It is the .NET 1.0 tax. IList also implements IEnumerable. The non-generic one that spits out collection members of type `object`. Which *might* be convertible to MyClass. C# would look very different if 1.0 never happened. – Hans Passant Dec 03 '18 at 10:08

0 Answers0