Abstract

This article will help you to understand the Nullable type implementation in C#. This article also explains about Coalescing Operator and how CLR has special support for Nullable value type.

Introduction

As we all know, a value type variable cannot be null. That's why they are called Value Type. Value type has a lot of advantages, however, there are some scenarios where we require value type to hold null also.

Consider the following scenario:

Scenario 1: You are retrieving nullable integer column data from database table, and the value in database is null, there is no way you can assign this value to an C# int.

Scenario 2: Suppose you are binding the properties from UI but the corresponding UI don't have data. (for example model binding in Asp.Net MVC or WPF). Storing the default value in model for value type is not a viable option.

Scenario 3: In Java, java.Util.Date is a reference type, and therefore, the variable of this type can be set to null. However, in CLR, System.DateTime is a value type and a DateTime variable cannot be null. If an application written in Java wants to communicate a date/time to a Web service running on the CLR, there is a problem if the Java application sends null because the CLR has no way to represent this and operate on it.

Scenario 4: When passing value type parameter to a function, if the value of parameter is not know and if you don't want to pass it, you go with default value. But default value is not always a good option because default value can also a passed parameter value, so, should not be treated explicitly.

Scenario 5: When deserializing the data from xml or json, it becomes difficult to deal with the situation if the value type property expects a value and it is not present in the source.

Likewise, there are many scenarios we faced in our day to day life.

To get rid of these situations, Microsoft added the concept of Nullable types to the CLR. To Understand this, have a look over the logical definition of System.Nullable<T> Type:

(Please note that below code snippet is the logical definition for illustration purpose only. Taken from "CLR Via C#, 3rd edition", written by Jeffrey Richter)

Nullable Type is of struct type that holds a value type (struct) and a Boolean flag, named HasValue, to indicate whether the value is null or not.

Since Nullable<T> itself is a value type, it is fairly lightweight. The size of Nullable<T> type instance is the same as the size of containing value type plus the size of a boolean.

The nullable types parameter T is struct. i.e., you can use nullable type only with value types. This is quite ok because reference types can already be null. You can also use the Nullable<T> type for your user defined struct.

Nullable type is not an extension in all the value types. It is a struct which contains a generic value type and a boolean flag.

Syntax and Usage

To use Nullable type, just declare Nullable struct with a value type parameter, T, and declare it as you are doing for other value types.
For example,

Nullable<int> i = 1;
Nullable<int> j = null;

Use Value property of Nullable type to get the value of the type it holds. As the definition says, it will return the value if it is not null, else, it will throw an exception. So, you may need to check for the value being null before using it.

The Coalescing Operator

C# provides you quite a simplified syntax to check null and simultaneously assign another value in case the value of the variable is null. This can be used in Nullable types as well as reference types.

You can also chain it, which may save a lot of coding for you. See the example below:

// Here is an example where a developer is setting the address of a Customer. // The business requirement says that:// (i) Empty address is not allowed to enter // (Address will be null if not entered). (ii) Order of precedence of // Address must be Permanent Address which if null, Local Address which if null, // Office Address.// The following code does this:string address = string.Empty;
string permanent = GetPermanentAddress();
if (permanent != null)
address = permanent;
else
{
string local = GetLocalAddress();
if (local != null)
address = local;
else
{
string office = GetOfficeAddress();
if (office != null)
address = office;
}
}
//With Coalescing Operator, the same can be done in a single expression.//string address = GetPermanentAddress() ?? GetLocalAddress()
?? GetOfficeAddress() ?? string.Empty;

The code above with Coalescing operator is far easier to read and understand than that of a nested if else chain.

Boxing and UnBoxing of Nullable types

Since I have mentioned earlier that the Nullable<T> is still a value type, you must understand performance while boxing and unboxing of Nullable<T> type.

The CLR executes a special rule to box and unbox the Nullable types. When CLR is boxing a Nullable instance, it checks to see if the value is assigned null. In this case, CLR does not do anything and simply assigns null to the object. If the instance is not null, CLR takes the value and boxes it similar to the usual value type.

While unboxing to Nullable type, CLR checks If an object having its value assigned to null. If yes, it simply assigns the value of Nullable type to null. Else, it is unboxing as usual.

Calling GetType() for Nullable Type

When calling GetType() for Nullable<T> type, CLR actually lies and returns the Type the Nullable type it holds. Because of this, you may not be able to distinguish a boxed Nullable<int> was actually a int or Nullable<int>.
See the example below:

Points of Interest

Note that I haven't discussed the details of memory allocation and object creation while boxing and unboxing to keep the article focused to Nullable types only. You may Google it for details about boxing and unboxing.

Conclusion

Since Nullable Type is also a value type and fairly lightweight, don't hesitate to use it. It is quite useful in your data driven application.

Share

About the Author

Anurag Gandhi currently works in web application design/development and has done so for many years now as he is passionate about programming.
He is extensively involved in Asp.Net and Asp.Net MVC web application architecture, AngularJs, design and development. His languages of choice are C#, Asp.Net, MVC, Asp, C, C++. But he is familiar with many other coding languages. He works with MS Sql Server as the database architecture of choice.
He is active in programming communities and loves to share his knowledge with other developers whenever he gets the opportunity.
He is also a passionate chess player.

When boxing a nullable field into a non-nullable field, it is critical that the boxed item isn't null before trying to box the non-null field or try-catch handles the problem. You should supply the consequences of ignoring that requirement in your article. For instance, outside of a try block executing

int? tst = null;
int tst2 = (int)tst;

results in:

An unhandled exception of type 'System.InvalidOperationException' occurred in mscorlib.dll
Additional information: Nullable object must have a value.

Not executing this in a debug session might lose even more information on what went wrong. There are plenty of other boxing errors that should be pre-checked. Like byte x = (byte) 354;
There are plenty of articles in CodeProject that are a rehash of documentation and information in books. If you are using them in your article, it should reference the exact sources you used, but I don't mind a re-hash of something I already know about.

Thanks for the suggestion.
I have already mention in the code block of related section that it will throw null reference exception.
Regarding references, I am re-collecting the sources from where I took the information. I will soon provide a reference section too. Thank you.

Life is a computer program and everyone is the programmer of his own life.

1. Never Post Untested Code. You cannot initialize the fields in a struct.

2. You should always write code with clearness and fullness especially when you pretend to be teaching others. Usage of lowercase <t> in the typed struct and then with upper case in the where T definition is really bad. And this inconsistency goes throughout the code.

3. This should never be in Code Project at all as this is by definition in the documentation of .NET Framework and MSDN everywhere. Just because you pick 2-3 pages from there doesn't mean you should make an article about it. And just because you find 10 - 15 people who are just starting coding you shouldn't feel proud about yourself as a good article writer.

His points are valid but the way he wrote was an insult instead of feedback.
I would not like to debate on it.

I have already updated my article based on his comment (whatever was possible).

Its not only about 10-15 people, when you need information, you really look for detailed explanation which should be more than mere documentation like msdn. If everyone understand from MSDN, then I agree, there should not be any tutorial article on any .net topic(s).

Life is a computer program and everyone is the programmer of his own life.

The article is too similar to the Chapter 19 of the book "CLR via C#, 3rd edition", written by Jeffrey Richter. Sequence of topics is equivalent, your article being shortened when dealing with operators. Just as an example, your article starts with:

"As we all know, a value type variable cannot be null. That's why they are called Value Type. Value type has a lot of advantages, however, there are some scenarios where we require value type to hold null also. ...
...In Java, java.Util.Date is a reference type, and therefore, the variable of this type can be set to null. However, in CLR, System.DateTime is a value type and a DateTime variable cannot be null. If an application written in Java wants to communicate a date/time to a Web service running on the CLR, there is a problem if the Java application sends null because the CLR has no way to represent this and operate on it."

On the other hand, Chapter 19 in Richter's book (page 459) starts with:

"As you know, variable of value type can never be null; it always contains the value type's value itself. In fact, this is why they call these types value types. Unfortunately, there are some scenarios in which this is a problem...
...in Java, java.Util.Date is a reference type, and therefore, a variable of this type can be set to null. However, in CLR, System.DateTime is a value type and a DateTime variable cannot be null. If an application written in Java wants to communicate a date/time to a Web service running the CLR, there is a problem if the Java application sends null because the CLR has no way to represent this and operate on it."

There is a number of completely transcribed or only slightly modified sentences. However, you didn't even mention any reference to Richter's book!

IMHO you should add this immediately since your article is violating copyright of the original text. It is like you steal something and say "I'll return it when I will be passing the place where I stole from".

Well, I do not agree completely with you here as a copyright rule is quite complex and have a lot of clauses. But I understand that if my article is inspired/abstracted from some place, I should provide the reference.

Anyways, I have added the reference. Thanking you for pointing it out.

Life is a computer program and everyone is the programmer of his own life.