Most developers know that in C#, we have mainly the two types : Reference type and Value type. But we have one more type, that is called a Nullable type.
Actually it is a value type but it has features of both Reference and Value type. It has the capability to hold a value or can have a null reference, in other words there is no value. Nullable types were introduced in .Net 2.0.
As we know, a value type is allocated space on a stack, and every value type must be initialized to some value when declared. If you don't provide it by yourself then C# does it for you. So every value type is assigned a value whether you initialize it or not.
The issue with value type is that it's always has some value whether we assign it or not. If the variable has initial value then we cannot say that this is default value or initialized in the code. To overcome this issue the Nullable type was introduced.
We can declare and initialize a Nullable type as in the following:
- //This is a Nullable of Int type
- Nullable<int> t = 5;
- int? i = 5
- public struct Nullable<T> where T: struct
- {
- private bool hasValue;
- internal T value;
- public Nullable(T value);
- public bool HasValue { get; }
- public T Value { get; }
- public T GetValueOrDefault();
- public T GetValueOrDefault(T defaultValue);
- public override bool Equals(object other);
- public override int GetHashCode();
- public override string ToString();
- public static implicit operator T?(T value);
- public static explicit operator T(T? value);
- }
Here we will discuss specific properties of Nullable type that are relevant to this topic. Now let's go to the details of the method public Nullable(T value). This is a parametrized constructor. Now let's see what is inside this code:
- public Nullable(T value)
- {
- this.value = value;
- this.hasValue = true;
- }
- public bool HasValue
- {
- get
- {
- return this.hasValue;
- }
- }
- Nullable<int> t = new Nullable<int>()
Now let's see what public T Value { get; } does:
- public T Value
- {
- get
- {
- if (!this.HasValue)
- {
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
- }
- return this.value;
- }
- }
Also let's have a view of two more next methods public T GetValueOrDefault() and public T GetValueOrDefault(T defaultValue). As the method name suggests, that returns the existing value and if it is not set then the type's default value is returned. The definition is like this:
- public T GetValueOrDefault()
- {
- return this.value;
- }
- public T GetValueOrDefault(T defaultValue)
- {
- if (!this.HasValue)
- {
- return defaultValue;
- }
- return this.value;
- }
So you can see it checks the HasValue and based on this return the result. Similarly if you want to see a public override bool Equals(object other) method then it has the code like:
- public override bool Equals(object other)
- {
- if (!this.HasValue)
- {
- return (other == null);
- }
- if (other == null)
- {
- return false;
- }
- return this.value.Equals(other);
- }
This also checks the HasValue before comparing it. So we have gone through the underlying implementation of Nullable type.
Note - I have picked the underlying implementation using Reflector for better understanding.
There are two operator's method you can see at last. You all must be knowing this is Operator Overloading. But what is this for? Let's see the code below:
- int i = 5;
- //Assigning a int type to a Nullable of int
- Nullable<int> t = i;
So it means, we can assign a value type to a Nullable type that underlying type is the same as an underlying type of a Nullable type without any casting.
But reverse is not possible. You need to do an explicit cast as:
- Nullable<int> t = 5;
- //Need an explicit cast
- int i = (int)t;
- Nullable<int> t = 5;
- // No need for a cast because t.Value is actually the underlying type and holds the value
- int i = t.Value;
First scenario
It will be compiled successfully but will throw and an Invalid Cast Exception. In other words, you cannot cast it to any other type except the underlying type that is here int although int type can be held by long.
- int? a=8;
- object o = a;
- long d = (long)o;
But the following lines will run successfully:
Because here we are converting to an underlying type int that we can assign to long as it is a widening conversion.
- long d = (int)o;
- long? d = (int)o;
Now let's move to another point.
Second scenario
Guess what will be the output of the following lines:
Is it System.Nullable<Int32>. No
- int? b=5;
- Console.WriteLine(b.GetType());
This actually shows System.Int32. So beware.
Few more things
We can use a Unary operator over Nullable type. It will be null if it has no value or null else applies the operator.
Binary operators also can be used with a Nullable type. Give it a view:
This will print 12. But what if:
This will print nothing because the addition result will be null. So be sure, during any binary operation if one operand (or does not have any value) is null. The result will also be null (or would not have any value).
- int? b=5;
- int? a = 7;
- Console.WriteLine(a+b);
- int? b=5;
- int? a=null;
- Console.WriteLine(a+b);
I hope you have enjoyed the article.

Saineshwar BageriPosted Jun 6, 2014, 3:31 AM
Good article :)
Akhil MittalPosted Jun 4, 2014, 1:22 AM
Though the intention to clarify the concept was very clear, but there are few points I would like to take which I came across while reading the article, 1. I think the line "Here we will the some main properties of Nullable type and leave default ones" is not grammatically correct. 2. In the code snippet as mentioned as, "Now let's see what is inside this code: public Nullable(T value) { this.value = value; this.hasValue = true; } Here you can see that this is assigning a value to the variable and setting hasValue to true. Now let's see the HasValue property. public bool HasValue { get { return this.hasValue; } } So it actually has one property hasValue that does the entire job. By default it is set to false and once we assign a value to it, it is set to true. So whenever one accesses it without assigning it a value it returns a null reference." You say that in the default code this.hasValue is set to true as shown in code snippet, but after showing the HasValue Property you contradict your statement by saying that by default it was set to false, and you say whenever we access that value without assigning it it will give null reference exception.My question is why will it give null ref exception if in the code as shown here already contains a default value as true or false as per your statement? 3.In the code snippet, " "public override bool Equals(object other) { if (!this.HasValue) { return (other == null); } if (other == null) { return false; } return this.value.Equals(other); } This also checks the hasValue before comparing it." You say that it checks hasVlue, but actually its checking the property and not the class variable, so it should be HasValue. 4.In the code snippets as mentioned in below lines "First scenario Int? a=8; object o = a; long d = (long)c; It will be compiled successfully but will throw and an Invalid Cast Exception. In other words, you cannot cast it to any other type except the underlying type that is here int although int type can be held by long. But the following lines will run successfully: long d = (int)c; long? d = (int)c;" You talk about variable "c" but its not declared anywhere, the variable that you declared was Int? a, so please correct it to avoid confusion. 5.I tried to run the code Int? a=8; but it gives compile time error it takes int?a=8 and not capital Int.Please elaborate. 6. I executed the last code snippet, int? b=5; int? a=null; Console.WriteLine(a b); it writes nothing like you said, but when I assigned the a b vaue to var c as var c=a b and printed c, it showed the same behavior and in debug window it says c is null, but if i write Console.Writeline(null), it gives compile time error.Please explain this as this is a point of doubt. 7.There are some more grammatical mistakes in the post, please fix.
Pankaj BajajPosted Apr 30, 2014, 1:24 AM
really it's an very informative article..Thanks Brij.
Lakshmanan Sethu SankaranarayanPosted Apr 30, 2014, 1:02 AM
Good article :)
Mahesh ChandPosted Apr 29, 2014, 7:53 AM
Good start Brij. Yes agree with DJ. Formatting of code snippet is good in the editor using the Code tag. Also, people may want to copy the code snippet.
Former memberPosted Apr 29, 2014, 1:38 AM
I guess if we use code snippet instead of images then it would be more valuable. In between it is very informative post !