如果我有两个班级,A
和B
,其中B派生自A:
class A {}
class B : A { }
我可以非常高兴地将B
的实例转发给A
。
B b = new B();
A a = b;
现在,我可以理解运行时如何确定底层类型是B,如ECMA-335(公共语言基础结构(CLI)分区I到VI)的第132页所述
实例化类型的对象应携带足够的信息 在运行时恢复它们的确切类型(包括类型和数量) 他们的通用论点)。 [理由:这是正确的 实现铸造和测试实例,以及反思 功能
那么,运行时如何知道虽然底层类型是B
,但它实际上存储在A
中。我知道我不会在B
上看到可用的方法,但如果基础类型是B
,它如何存储存储位置的类型A
?< / p>
这有意义吗?
答案 0 :(得分:7)
对象是B,CLI知道它是B.知道A的东西主要是编译器,然后声明字段或 local 作为类型A(或者,在某些情况下,类似于方法链接,类型通过方法的返回类型已知,该方法被刻印到调用者的 IL中)。所以基本上:调用代码本身就是“我认为这是一个A”。作业等通常都是事先可以验证的,所以不存在弄错的风险。如果你试图破解IL故意弄错,运行时会告诉你并拒绝运行该方法。由于这些原因,将已知的B值分配给A本地/字段不需要任何类型检查 - 它只是一个直接分配。
答案 1 :(得分:3)
对象的实际类型始终与对象本身一起存储在堆上。指向该对象的引用可以是不同的类型,只要该类型可以从实际类型(例如,基类或该类型的已实现接口)分配。
堆上的每个对象都存储着少量数据 - 该对象的类型就是其中之一。