Elements of the CLR Type System
Figure 2.2 depicts the basic CLR type system. The type system is logically
Figure 2.2 The CLR type systemdivided into two subsystems, value types and reference types.
A value type consists of a sequence of bits in memory, such as a 32-bit integer. Any two 32-bit integers are considered equal if they hold the same numberthat is, if the sequence of bits is identical.
Reference types combine the address of a value (known as its identity) and the value's sequence of bits. Reference types can, therefore, be compared using both identity and equality. Identity means that two references refer to the same object; equality means that two references refer to two different objects that have the same datathat is, the same sequence of bits.
On a more practical level, references types differ from value types in the following ways:
Value types always directly inherit from System.ValueType or System.Enum, which itself inherits from System.ValueType. The types are always sealed, which means that no other types can inherit from them. Reference types, in contrast, inherit from any class other than System.ValueType or System.Enum. Reference types are always allocated on the garbage collected heap, whereas value types are normally allocated on the stack. Note, however, that value types may be allocated on the garbage collected heapfor instance, as members of reference types.
Reference types are accessed via strongly typed references. These references are updated if the garbage collector moves an object.
As mentioned previously, in CLR terminology, an instance of any type (value or reference) is known as a value. Every value in the CLR has one exact type, which in turn defines all methods that can be called on that value.
In Figure 2.2, note that the User-Defined Reference Types box does not connect with the Pointer Types box. This fact is sometimes misconstrued as meaning that pointers cannot point to user-defined types. This is not the case, however; rather, the lack of a connection means that developers cannot define pointer types but the CLR will generate pointers to user-defined types as needed. This situation is similar to that observed with arrays of user-defined types: Developers cannot define these arrays but the CLR generates their definitions whenever they are needed.