All types fall into two categories: value typesand reference types. The differences between the types in each category stem from the fact that each category uses a different location in memory: Value type data is stored on the stack and reference type data is stored on the heap.
With the exception of string, all the predefined types in the book so far are value types. Value types contain the value directly. In other words, the variable refers to the same location in memory where the value is stored. Because of this, when a different variable is assigned the same value, a memory copy of the original variable's value is made to the location of the new variable. A second variable of the same value type cannot refer to the same location in memory as the first variable. So changing the value of the first variable will not affect the value in the second. Figure 2.1 demonstrates this.number1 refers to a particular location in memory that contains the value 42. After assigning number1 to number2, both variables will contain the value 42. However, modifying either value will not affect the other.
Figure 2.1. Value Types Contain the Data Directly
Similarly, passing a value type to a method such as Console.WriteLine() will also result in a memory copy, and any changes to the parameter value inside the method will not affect the original value within the calling function. Since value types require a memory copy, they generally should be defined to consume a small amount of memory (less than 16 bytes).
The amount of memory required for the value type is fixed at compile time and will not change at runtime. This fixed size allows value types to be stored in the area of memory known as the stack.
Reference types and the variables that refer to them point to the data storage location. Reference types store the reference (memory address) where the data is located instead of storing the data directly. Therefore, to access the data the runtime will read the memory location out of the variable and then jump to the location in memory that contains the data. The memory area of the data a reference type points to is the heap (see Figure 2.2).
Figure 2.2. Reference Types Point to the Heap
Since accessing reference type data involves an extra hop, sometimes it behaves slightly slower. However, a reference type does not require the same memory copy of the data that a value type does, resulting in circumstances when it is more efficient. When assigning one reference type variable to another reference type variable, only a memory copy of the address occurs, and as such, the memory copy required by a reference type is always the size of the address itself. (A 32-bit processor will copy 32 bits and a 64-bit processor will copy 64 bits, and so on.) Obviously, not copying the data would be faster than a value type's behavior if the latter's data size is large.
Since reference types copy only the address of the data, two different variables can point to the same data. Furthermore, changing the data through one variable will change the data for the other variable as well. This happens both for assignment and for method calls. Therefore, a method can affect the data of a reference type back at the caller.
Besides string and any custom classes such as Program, all types discussed so far are value types. However, most types are reference types, and although it is possible to define custom value types, it is relatively rare to do so in comparison to the number of custom reference types.