6

如果我有两个类,A并且BB 从 A 派生:

class A {}
class B : A { }

我可以很高兴地向上B转换 to的一个实例A

B b = new B();
A a = b;

现在,我可以理解运行时如何确定底层类型是 B,正如ECMA-335(通用语言基础设施(CLI)分区 I 到 VI)的第 132 页所述

实例化类型的对象应携带足够的信息以在运行时恢复其确切类型(包括其泛型参数的类型和数量)。[理由:这是正确实现强制转换和测试实例以及反射功能所必需的

那么,运行时如何知道虽然底层类型是B它实际上存储在一个A. 我知道我不会看到可用的方法B,但如果基础类型是B,它如何存储存储位置的类型A

那有意义吗?

4

2 回答 2

7

对象是 B,CLI 知道它是 B。了解 A 的主要是编译器,然后编译器将字段本地声明为 A 类型(或者,在某些情况下,如方法链接,类型是通过方法的返回类型知道的,它被硬标记到调用者的IL 中)。所以基本上:调用代码本身就是“我认为这是一个 A”。作业等通常都是可以提前验证的,因此没有出错的风险。如果你试图破解 IL 故意弄错它,运行时会告诉你并拒绝运行该方法。由于这些原因,将已知为 B 的值分配给 A 本地/字段不需要任何类型检查 - 它只是直接分配。

于 2012-10-23T19:11:44.910 回答
3

对象的实际类型始终与对象本身一起存储在堆上。指向该对象的引用可以是不同的类型,只要该类型可以从实际类型中分配(例如,该类型的基类或实现的接口)。

堆上的每个对象都存储了少量数据——该对象的类型就是其中之一。

于 2012-10-23T19:12:04.770 回答