There are two types of data types in the .NET framework: Value and reference types.
Lets first have a look at the value types:
- Value types are allocated on the current thread’s stack.
- The lifetime of the value type is only inside the scope where it is used.
- When you pass a value type as a parameter in a method, the value type is copied.
- A wrapper object is created if you pass a value type to a method that expects an object.
Value types are suitable for representing lightweight objects such as vectors, matrices and colors. Value types has less overhead than classes by the fact that no additional memory for the reference is needed. However, there are a few things that are worth mentioning:
- Structs can’t have a default parameterless constructor. It is provided by default and it initializes all the fields to their default values.
- You can’t initialize an instance field inside a struct
- You can’t use inheritance in structs
Value types are important for performance since they are allocated on the stack (the stack is not garbage collected) – they are cheaper to allocate and deallocate than classes. However, if your struct is more than 16 bytes, it may be more efficient to use a class instead.
Now, let us have a look at reference types:
- Stored on the managed heap.
- Variables that are reference types only contain a pointer to the data.
- Reference types are garbage collected when they are no longer referenced.
- Are always passed by reference (the pointer to the data is passed)
For your convenience, here is a list of value and reference types:
|Value types||Reference types|
The ref keyword
The ref keyword is very important when it comes to both performance and the behavior of value and reference types. If you put ref in front of a parameter in a method, the argument is passed by reference regardless whether it is a value or reference type.
The output of this application is “http://google.it”. If we didn’t have the ref keyword in front of the parameter, the output would be “http://google.com”. This is because the original pointer (reference) to the data is passed to the method when using the ref keyword. Value types can also be passed to the method by reference (and no, it does not get boxed) – yielding the same behavior as the reference type.