编译时和运行时转换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
的静态类型现在是Base
。 Base
类型的某些东西可能具有动态类型Derived
,因此这是一个向下转换。 通常,编译器无法从x
的静态类型知道运行时类型是Base
的某个其他子类的Base
, Derived
。 因此,是否允许转换的决定留给运行时。
如果你的变量是Base
类型,理论上可以由Derived
构造函数构造,因此实际上是Derived
类型的变量。 在编译时,编译器不会打扰自己,试图弄清楚在每个特定情况下是否可以进行这种向下转换(将Base
类型的变量表示为Derived
类型的实体)。
您的示例很简单 – 您创建一个新类并立即投射它。 但是,如果你从其他地方获得Base
,例如,某些方法调用呢? 编译器只是无法“猜测”你的方法将返回什么,因此不会抛出错误。
当您转换Other
,编译器会发现Other
实际上不可能Derived
并抛出exception。