Using Nullable Types
This is my first post. I would be posting many .NET post in coming days.
Today we would be learning what are Nullable Types in .NET
Nullable types can represent all the values of an underlying type, and an additional null value.
Nullable types are declared in one of two ways:
System.Nullable<T> variable
-or-
T? variable
T is the underlying type of the nullable type. T can be any value type including struct; it cannot be a reference type.
For an example of when you might use a nullable type, consider how an ordinary Boolean variable can have two values: true and false. There is no value that signifies "undefined". In many programming applications, most notably database interactions, variables can occur in an undefined state.
For example,
A field in a database may contain the values true or false, but it may also contain no value at all. Similarly, reference types can be set to null to indicate that they are not initialized.
Any value type may be used as the basis for a nullable type. For example:
int? i = 10;
double? d1 = 3.14;
bool? flag = null;
char? letter = 'a';
int?[] arr = new int?[10];
Each instance of a nullable type has two public read-only properties:
HasValue
HasValue is of type bool. It is set to true when the variable contains a non-null value.
Value
If HasValue is true, Value contains a meaningful value. If HasValue is false, accessing Value will throw a InvalidOperationException.
Lets consider an example
In this example, the HasValue member is used to test whether the variable contains a value before it tries to display it.
int? x = 10;
if (x.HasValue)
{
System.Console.WriteLine(x.Value);
}
else
{
System.Console.WriteLine("Undefined");
}
Testing for a value can also be done as in the following example:
int? y = 10;
if (y != null)
{
System.Console.WriteLine(y.Value);
}
else
{
System.Console.WriteLine("Undefined");
}
A nullable type can be cast to a regular type, either explicitly with a cast, or by using the Value property. For example:
int? n = null;
//int m1 = n; // Will not compile.
int m2 = (int)n; // Compiles, but will create an exception if n is null.
int m3 = n.Value; // Compiles, but will create an exception if n is null.
A variable of nullable type can be set to null with the null keyword, as shown in the following example:
int? n1 = null;
The conversion from an ordinary type to a nullable type, is implicit.
int? n2;
n2 = 10; // Implicit conversion.
These operators produce a null value if the operands are null; otherwise, the operator uses the contained value to calculate the result. For example:
int? a = 10;
int? b = null;
a++; // Increment by 1, now a is 11.
a = a * 10; // Multiply by 10, now a is 110.
a = a + b; // Add b, now a is null.
When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal). It is important not to assume that because a particular comparison returns false, the opposite case returns true. In the following example, 10 is not greater than, less than, nor equal to null. Only num1 != num2 evaluates to true.
Example
int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
Console.WriteLine("num1 is greater than or equal to num2");
}
else
{
// This clause is selected, but num1 is not less than num2.
Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)");
}
if (num1 < num2)
{
Console.WriteLine("num1 is less than num2");
}
else
{
// The else clause is selected again, but num1 is not greater than
// or equal to num2.
Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)");
}
if (num1 != num2)
{
// This comparison is true, num1 and num2 are not equal.
Console.WriteLine("Finally, num1 != num2 returns true!");
}
// Change the value of num1, so that both num1 and num2 are null.
num1 = null;
if (num1 == num2)
{
// The equality comparison returns true when both operands are null.
Console.WriteLine("num1 == num2 returns true when the value of each is null");
}
/* Output:
* num1 >= num2 returned false (but num1 < num2 also is false)
* num1 < num2 returned false (but num1 >= num2 also is false)
* Finally, num1 != num2 returns true!
* num1 == num2 returns true when the value of each is null
*/
An equality comparison of two nullable types that are both null evaluates to true.
Nullable types have the following characteristics:
· Nullable types represent value-type variables that can be assigned the value of null.
· The syntax T? is shorthand for Nullable<T>, where T is a value type. The two forms are interchangeable.
· Assign a value to a nullable type just as you would for an ordinary value type, for example int? x = 10; or double? d = 4.108. A nullable type can also be assigned the value null: int? x = null.
· Use the Nullable<T>.GetValueOrDefault method to return either the assigned value, or the default value for the underlying type if the value is null, for example int j = x.GetValueOrDefault();
· Use the HasValue and Value read-only properties to test for null and retrieve the value, as shown in the following example: if(x.HasValue) j = x.Value;
· The HasValue property returns true if the variable contains a value, or false if it is null.
· The default value for HasValue is false. The Value property has no default value.
· You can also use the == and != operators with a nullable type, as shown in the following example: if (x != null) y = x;
· Use the ?? operator to assign a default value that will be applied when a nullable type whose current value is null is assigned to a non-nullable type, for example int? x = null; int y = x ?? -1;
The ?? operator defines a default value that is returned when a nullable type is assigned to a non-nullable type.
C#
int? c = null;
// d = c, unless c is null, in which case d = -1.
int d = c ?? -1;
This operator can also be used with multiple nullable types. For example:
int? e = null;
int? f = null;
// g = e or f, unless e and f are both null, in which case g = -1.
int g = e ?? f ?? -1;
References