在 .net 的内部,包含某些成员的结构的定义与具有相同字段和成员的类的定义相同,并且继承自System.ValueType. 请注意,编译器不允许声明 aclass继承ValueType,但是当声明 a 时struct,编译器“在幕后”声明了一个继承的类。
.net 中值类型的特殊之处在于运行时分配存储位置(变量、字段、参数等)的方式。当ValueType声明不继承自的类型的存储位置时,运行时将为堆对象分配空间参考。相反,当声明继承自的类型的存储位置时ValueType,运行时将为该类型的所有公共和私有字段分配空间。对于类似 的类型int,系统会在正常类型系统之外分配一个属于特殊原始类型的私有字段。
请注意,值类型的存储位置并不真正保存该类型的实例。相反,它是该类型的一个实例,并包含该类型的所有字段。语句 likestruct1 = struct2不会将值类型实例struct1替换为实例struct2。struct2相反,它会从中的相应字段复制所有字段struct1。同样,如果将值类型存储位置作为方法传递给过程而不使用ref关键字,则传递的不是结构实例本身,而是其字段的内容。
如果需要将值类型的存储位置复制到非派生的类型ValueType(例如Objector IComparable),系统将创建一个新的值类型的堆对象实例,将值类型的所有字段复制到该值类型new instancen 并将对该新实例的引用存储在目标存储位置。这个过程称为“装箱”。大多数编译器会隐式执行此操作,因此试图表现得好像值类型存储位置包含一个派生自ValueType. 不过,重要的是要注意,这是一种错觉。如果 typeX派生自Y,一个有一个Xnamedxx和一个Ynamedyy并且一个执行xx = yy,这样的语句应该导致xx和yy引用相同的对象实例。如果xx并且yy不是从 派生的类型ValueType,即使yy持有从 派生的某物的实例,也会发生这种情况ValueType。但是,如果xx和/或yy源自ValueType. 在这种情况下,系统会将字段从一个实例复制到另一个(可能是新的)实例。