编译时和运行时转换c#

我想知道为什么在编译时检查C#中的某些转换,而在其他情况下,责任转储到CLR上。 如上所述都是不正确的,但以不同的方式处理。

class Base { } class Derived : Base { } class Other { } static void Main(string[] args) { Derived d = (Derived)new Base(); //Runtime InvalidCastException Derived d = (Derived)new Other(); //Compile-time Cannot convert type... } 

在阅读“C#深度”时,我发现了有关此主题的信息,其中autor说:
“如果编译器发现该转换实际上不可能工作,它将触发编译错误 – 如果理论上允许但在执行时实际上不正确,则CLR将抛出exception。”

“理论上”是否意味着通过inheritance层次结构(对象之间的另一个亲和力?)连接,还是编译器的内部业务?

  • 可以在编译时检查向上转换 – 类型系统保证转换成功。
  • 在编译时不能(通常)检查downcast,因此总是在运行时检查它们。
  • 不相关的类型不能相互转换。

编译器仅考虑静态类型。 运行时检查动态(运行时)类型。 看看你的例子:

 Other x = new Other(); Derived d = (Derived)x; 

x的静态类型是Other 。 这与Derived无关,因此转换在编译时失败。

 Base x = new Base(); Derived d = (Derived)x; 

x的静态类型现在是BaseBase类型的某些东西可能具有动态类型Derived ,因此这是一个向下转换。 通常,编译器无法从x的静态类型知道运行时类型是Base的某个其他子类的BaseDerived 。 因此,是否允许转换的决定留给运行时。

如果你的变量是Base类型,理论上可以由Derived构造函数构造,因此实际上是Derived类型的变量。 在编译时,编译器不会打扰自己,试图弄清楚在每个特定情况下是否可以进行这种向下转换(将Base类型的变量表示为Derived类型的实体)。

您的示例很简单 – 您创建一个新类并立即投射它。 但是,如果你从其他地方获得Base ,例如,某些方法调用呢? 编译器只是无法“猜测”你的方法将返回什么,因此不会抛出错误。

当您转换Other ,编译器会发现Other实际上不可能Derived并抛出exception。