Ema*_*rsa 7 c# generics nested-generics
我有以下代码:
IEnumerable<IList<MyClass>> myData = //...getMyData
foreach (MyClass o in myData)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
它编译,运行,显然我得到了System.InvalidCastException.
为什么编译器不抱怨?MyClass是一个简单的bean,没有扩展名.
编辑1:
正如David所建议的那样,将类型IList转换List为编译器抱怨
编辑2:
我已经明白行为是在C#语言定义中指定的.但是,我不明白为什么允许这样的转换/转换,因为在运行时我总是得到一个InvalidCastException.为了更深入,我打开了这个.
好吧因为IList<MyClass>是一个接口所以理论上你可以有一个实现该接口和派生的类MyClass.
如果将其更改为IEnumerable<List<MyClass>>它将无法编译.
在任何情况下,至少我得到了多疑的警告,因为有其中来自继承的解决方案没有阶级IList<MyClass>和MyClass.
当foreach编译a时,它遵循的模式不是特定的类型(就像LINQ和awaitdo一样).
foreach不是在找一个IEnumerable或者IEnumerable<T>是一个有GetEnumerator()方法的类型(IList<T>确实如此).外部列表中的对象可以是派生自MyClass和实现的类型IList<T>.
IE浏览器.编译器执行轻量级"匹配模式"检查不是一个完整的检查.
请参阅C#5语言规范的§8.8.3,其中详细介绍了这一点(你会看到我上面的内容相当简单:即使IEnumerator没有检查,只是有MoveNext()方法和Current属性).
IList<MyClass> 可转换为MyClass.
但如果你实际上使用非空枚举来运行它,
\n\nIEnumerable<IList<MyClass>> myData = new IList<MyClass>[1] { new List<MyClass>() {new MyClass()}};\nRun Code Online (Sandbox Code Playgroud)\n\n你会得到这个错误:
\n\n\n\n\n无法将“System.Collections.Generic.List`1[MyClass]”类型的对象强制转换为“MyClass”类型。
\n
这符合规范:
\n\n\n\n\n第 8.8.4 节 foreach 语句
\n\n...\n 如果没有从 T(元素类型)到 V(foreach 语句中的局部变量类型)的显式转换 (\xc2\xa76.2),则会产生\n 错误并且没有采取进一步的措施。
\n\n...
\n
有一个IList<MyClass>从到 的显式转换MyClass(尽管它会在运行时失败),因此不会产生错误。
\n\n第 6.2.4 节 显式引用转换
\n\n显式引用转换为:
\n\n\n
\n\n- 从对象和动态到任何其他引用类型。
\n- 从任何类类型 S 到任何类类型 T,前提是 S 是 T 的基类。
\n- 从任何类类型 S 到任何接口类型 T,只要 S 不是密封的并且 S 不实现 T。
\n- 从任何接口类型 S 到任何类类型 T,前提是 T 不是密封的或者假设 T 实现了 S。
\n...
\n
| 归档时间: |
|
| 查看次数: |
163 次 |
| 最近记录: |