为什么C#编译器允许它编译并在运行时引发运行时异常?
class Program
{
static void Main(string[] args)
{
IEnumerable<Test> list = new List<Test>() { new Test() };
foreach(IDisposable item in list)
{
}
}
}
public class Test
{
}
这确实可以与任何接口一起编译,如果将IDisposable替换为具体类,则不会编译。
答案 0 :(得分:12)
foreach
循环中包含一个隐式强制转换。大概是这样的:
using (IEnumerator<Test> iterator = list.GetEnumerator())
{
while (iterator.MoveNext())
{
IDisposable item = (IDisposable) iterator.Current;
// Body of foreach loop here
}
}
回到泛型之前,这比必须强制转换源代码要容易得多。现在,它并不是那么重要,但是如果不进行编译将是很奇怪的。请注意,编译器 将检查其是否至少是可行。如果您使用foreach (string item in list)
不会编译,因为Test
不能是string
-但是Test
可以是{ {1}},因为它可以引用实现IDisposable
的{{1}}子类的实例。如果将Test
类密封,那么即使使用IDisposable
,它也将无法编译,因为那样的话,Test
实例将无法实现IDisposable
。
基本上,如果从Test
到迭代类型的强制转换会编译,它将编译,否则将编译失败。但是,如果正常的转换也将在执行时失败,则在执行时也会失败。