C#for IEnumerable< IList< object>编译但不应该 [英] C# foreach on IEnumerable<IList<object>> compiles but shouldn't

查看:59
本文介绍了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


我了解该行为是 C#语言定义.但是,我不明白为什么允许这样的转换/转换,因为在运行时我总是会收到InvalidCastException.我在以下位置打开了为了更深入.

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.

...

这篇关于C#for IEnumerable&lt; IList&lt; object&gt;编译但不应该的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆