Nullable Types

In C# a value of null can be assigned to reference types, or more specifically to nullable types. When a reference is set to null it means it is not pointing to any object. A value of null is perfectly legal for reference types.

C# is a strongly typed language and the concept of reference and value types is at the core of the language semantics. For example it is not possible to override the ?? operator because it would allow the developers to potentially break the boundary between reference and value types. In case you are asking what is this ‘??’ operator, it is called the null-coalescing operator, and it allows for a short-hand comparison and assignment like this:

 string firstString = default(string);

 string secondString = firstString ?? "apples";

In the above, secondString is assigned to “apples” because the ?? operator works like this: if firstString is null, assign to “apples”, otherwise, assign to firstString. Note that if instead of “apples” I had some null-valued variable or just null, the result of this assignment would be null.

If you have encountered the null-coalescing operator before, I bet you did not know it can be nested! For example, the below code is legal. Can you work out what the value of thirdString will be?

 string firstString = default(string);

 string secondString = firstString ?? "apples";

 string thirdString = firstString ??
                      secondString ??

The value of thirdString will be set to “apples” because the nested null-coalescing works like nested if-else. So, the above can be read like this: if firstString is not null assign to its value, otherwise, if secondString is not null assign to its value, else assign to “pears”.

Value types cannot be used in null-coalescing. This is because it is not legal to assign a null to a value type. For example, something like this will never compile:

 int firstInt = null;

In C#, an int is the same as Int32 and is internally represented as a struct, which is a value type. There is another special struct called System.Nullable. It is special because it can represent any of the C# value types, plus, it can take on the null value. Can you already see where I am going with this? This means that it is possible to use the null-coalescing with value types if we make them nullable. To make a value type nullable one should use ? operator. For example:

 int? firstInt = null;
 int? secondInt = firstInt ?? 3;

firstInt is now a nullable type and can be used with the null-coalescing operator. Is there any boxing overhead once we make a value type nullable? No, there is not. The firstInt and secondInt integers are still value types, i.e. they are still structs. At no point they get boxed into objects. As a matter of fact, a compiler translates ?? operator into a set of load and Brtrtue instructions. A call to get_HasValue()
is made on firstInt, which returns false. Brtrue instruction see this and transfers the control to the load and assignment to 3.