Common Type System—Value Layout
Values are not self-describing at all. Rather they are just a glob of bytes that compose its state. Notice above that the pointer just refers to the first byte of our value, with no sync-block or method table involved. You might wonder how type checking is performed in the absence of any type information tagged to an instance. A method table does of course exist for each value type. The solution is that the location in which a value is stored may only store values of a certain type. This is guaranteed by the verifier.
For example, a method body can have a number of local slots in which values may be stored, each of
which stores only values of a precise type; similarly, fields of a type have a precise type. The size of the
storage location for values is always known statically. For example, the
SampleStruct above consumes
64 bits of space, because it consists of two 32-bit integers. Notice that there is no overhead—what you
see is what you get. This is quite different from reference types, which need extra space to carry runtime
type information around. In cases where structs aren’t properly aligned, the CLR will pad them; this
occurs for structs that don’t align correctly on word boundaries.
- Note that the layout of values can be controlled with special hints to the CLR. This topic is discussed below when we talk about the subject of fields.
Lastly, because values are really just a collection of bytes representing the data stored inside an instance,
a value cannot take on the special value of
null. In other words,
0 is a meaningful value for all value
Nullable<T> type adds support for nullable value types. We discuss this shortly.