我有以下代码:
IEnumerable<IList<MyClass>> myData = //...getMyData
foreach (MyClass o in myData)
{
// do something
}
它编译通过,并运行,但显然我得到了一个“System.InvalidCastException”错误。
为什么编译器不会报错?“MyClass”只是一个简单的bean,没有扩展。
编辑1:
如David所建议的,将类型从“IList”更改为“List”,编译器会报错。
编辑2:
我已经理解这种行为是符合C#语言定义的C# Language definition。然而,我不明白为什么允许这样的强制转换/转换,因为在运行时我总是会得到InvalidCastException。我打开this以深入了解。
MyClass
并实现了IList<MyClass>
。编译器不会检查您分配了什么,它只检查左侧声明的类型。如果您分配了new List<MyClassChild>()
并且MyClassChild
是一个子类并实现了IList<MyClass>
,那么该代码将完全有效。 - Tim Schmelterforeach
之外,仍然需要进行向下转换。也就是说,写成MyClass foo = myData.GetEnumerator().Current;
是不合法的 - 它需要显式转换为MyClass
。向下转换通常不是隐式的。因此,问题仍然是为什么foreach
会自动插入这样的转换。我猜想答案是为了让用户在泛型出现之前能够编写foreach (MyType x in myUntypedList)
。 - sepp2kforeach
总是有一个内置的显式转换,它们可以枚举List<Object>
并将其转换为您在循环变量类型中指定的任何内容。这将在运行时失败。当然,原因是foreach
比泛型早得多。 - Tim Schmelter