【问题标题】:Why does foreach skip compile time type checking on interface types?为什么 foreach 会跳过接口类型的编译时类型检查?
【发布时间】:2010-08-02 15:42:43
【问题描述】:

当我在 C# 中使用 foreach 循环时,如果项目类型是接口类型,似乎不会执行编译时类型检查。

例如

class SomeClass {}
interface SomeInterface {}

IEnumerable<SomeClass> stuff;
foreach(SomeInterface obj in stuff) { // This compiles - why!?
}

这将愉快地编译并在运行时引发异常,如果在编译时很清楚,这没有任何意义。如果我将项目类型从 SomeInterface 更改为另一个类,则恢复编译时类型检查:

IEnumerable<SomeClass> stuff;
foreach(Random obj in stuff) { // This doesn't compile - good!
}

当项类型是接口时,为什么没有编译时类型检查?

(这发生在 Visual Studio 2008 中的 .NET 3.5 SP1 中)

【问题讨论】:

  • 是的,我想知道(并且被咬过)同样的事情。期待知情人士的解答!

标签: c# visual-studio-2008 foreach static-typing


【解决方案1】:

在编译时不清楚程序的另一部分,可能在不同的项目中,是否有:

class SomeOtherClass : SomeClass, ISomeInterface
{
   public static IEnumerable<SomeClass> GetSomeStuff()
   {
      for( int i = 0; i<10; ++i)
         yield return new SomeOtherClass(i);
   }
}

现在运行时检查成功了。

如果您将SomeClass 标记为sealed,那么这是不可能的,并且在编译时再次可以知道强制转换永远不会起作用。

【讨论】:

  • 你说的是对的。我很惊讶 C# 采用“foreach”这种方法,因为它使语言不一致。例如,方法调用没有这种相同的行为。
  • 这不是不一致的,它与强制转换的行为相同,考虑:foreach (SomeClass obj in stuff) ((ISomeInterface)obj).SomeInterfaceMethod();
  • 令人惊讶的是(对我来说)foreach 有效地进行了隐藏的动态转换。变量赋值 ("a = b;") 或函数调用 ("myFunc(c);") 等其他事物不会静默执行动态转换。代码中的动态强制转换 (IMHO) 应该清晰明了。
  • 我应该妥善密封我的课程的另一个原因。
猜你喜欢
  • 2021-06-06
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 2020-02-08
  • 1970-01-01
  • 2020-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多