C#for IEnumerable< IList< object>编译但不应该
我有以下代码:
IEnumerable<IList<MyClass>> myData = //...getMyData
foreach (MyClass o in myData)
{
// do something
}
它编译,运行,显然我得到了System.InvalidCastException
.
为什么编译器不抱怨? MyClass
是一个简单的bean,没有扩展名.
It compiles, runs and obviously I get an System.InvalidCastException
.
Why does the compiler not complain? MyClass
is a simple bean, no extensions.
正如David所建议的,将类型从IList
切换为List
时,编译器抱怨
Edit 1:
As suggested by David switching the type from IList
to List
the compiler complains
我了解该行为是
Edit 2:
I've understood that the behaviour is as specified in the C# Language definition. However, I don't understand why such a cast/conversion is allowed, since at runtime I always get an InvalidCastException. I opened this in order to go deeper.
IList<MyClass>
可转换为MyClass
.
但是,如果您实际上使用非空枚举来运行它,
But if you actually run it with a non-empty enumerable,
IEnumerable<IList<MyClass>> myData = new IList<MyClass>[1] { new List<MyClass>() {new MyClass()}};
您收到此错误:
无法转换类型为'System.Collections.Generic.List`1 [MyClass]'的对象来键入'MyClass'.
Unable to cast object of type 'System.Collections.Generic.List`1[MyClass]' to type 'MyClass'.
这符合规范:
8.8.4节foreach语句
Section 8.8.4 The foreach statement
... 如果没有从T(该元素进行显式转换(第6.2节) 类型)转换为V(foreach语句中的局部变量类型), 错误产生,因此不采取进一步措施.
... If there is not an explicit conversion (§6.2) from T (the element type) to V (the local-variable-type in the foreach statement), an error is produced and no further steps are taken.
...
是从IList<MyClass>
到MyClass
的显式转换(尽管它将在运行时失败),因此不会产生任何错误.
There is an explicit conversion from IList<MyClass>
to MyClass
(though it will fail at runtime), so no error is produced.
第6.2.4节显式引用转换
Section 6.2.4 Explicit reference conversions
显式引用转换为:
- 从对象和动态到任何其他引用类型.
- 从任何类别类型S到任何类别类型T,只要S是T的基类.
- 从任何类类型S到任何接口类型T,只要未密封S并且未实现T.
- 从任何接口类型S到任何类类型T,只要未密封T或提供T实现S.
- From object and dynamic to any other reference-type.
- From any class-type S to any class-type T, provided S is a base class of T.
- From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
- From any interface-type S to any class-type T, provided T is not sealed or provided T implements S.
...