German Wear Discount Shop - Click Here Write for Dotnet-friends and earn for your each submission [Dot]Net-Friends
Skip Navigation Links
Home
Latest
Fast Code
Articles
Tutorials
Online Resources
Forums
Login   | Hi, Guest


Nullable types in C# 2.0

Written by omerkamal on Mar 10, 2007
What are nullable types?

Explanation:

Support for nullability across all types, including value types, is essential when interacting with databases, yet general purpose programming languages have historically provided little or no support in this area. Many approaches exist for handling nulls and value types without direct language support, but all have shortcomings. For example, one approach is to use a “special” value (such as −1 for integers) to indicate null, but this only works when an unused value can be identified. Another approach is to maintain boolean null indicators in separate fields or variables, but this doesn’t work well for parameters and return values. A third approach is to use a set of user-defined nullable types, but this only works for a closed set of types. C#’s nullable types solve this long standing problem by providing complete and integrated support for nullable forms of all value types.


Nullable types are constructed using the ? type modifier. For example, int? is the nullable form of the predefined type int. A nullable type’s underlying type must be a non-nullable value type.

A nullable type is a structure that combines a value of the underlying type with a boolean null ind icator. An instance of a nullable type has two public read-only properties: HasValue, of type bool, and Value, of the nullable type’s underlying type. HasValue is true for a non-null instance and false for a null instance. When HasValue is true, the Value property returns the contained value. When HasValue is false, an attempt to access the Value property throws an exception.


An implicit conversion exists from any non-nullable value type to a nullable form of that type. Furth ermore, an implicit conversion exists from the null literal to any nullable type. In the example

int? x = 123;
int? y = null;
if (x.HasValue)
Console.WriteLine(x.Value);
if (y.HasValue)
Console.WriteLine(y.Value);

the int value 123 and the null literal are implicitly converted to the nullable type int?. The example outputs 123 for x, but the second Console.WriteLine isn’t executed because y.HasValue is false.

Nullable conversions and lifted conversions permit predefined and user-defined conversions that operate on non-nullable value types to also be used with nullable forms of those types. Likewise, lifted operators permit predefined and user-defined operators that work for non-nullable value types also work for nullable forms of those types.


For every predefined conversion from a non-nullable value type S to a non-nullable value type T, a predefined nullable conversion automatically exists from S? to T?. This nullable conversion is a null propagating form of the underlying conversion: It converts a null source value directly to a null target value, but otherwise performs the underlying non-nullable conversion. Nullable conversions are furthermore provided from S to T? and from S? to T, the latter as an explicit conversion that throws an exception if the source value is null.

Some examples of nullable conversions are shown in the following.

int i = 123;
int? x = i;          // int --> int?
double? y = x;          // int? --> double?
int? z = (int?)y;         // double? --> int?
int j = (int)z;          // int? --> int

A user-defined conversion operator has a lifted form when the source and target types are both non-nullable value types. A ? modifier is added to the the source and target types to create the lifted form. Similar to predefined nullable conversions, lifted conversion operators propagate nulls.


A non-comparison operator has a lifted form when the operand types and result type are all non-nullable value types. For non-comparison operators, a ? modifier is added to each operand type and the result type to create the lifted form. For example, the lifted form of the predefined + operator that takes two int operands and returns an int is an operator that takes two int? operands and returns an int?. Similar to lifted conversions, lifted non-comparison operators are null propagating: If either operand of a lifted operator is null, the result is null.

The following example uses a lifted + operator to add two int? values:

int? x = GetNullableInt();
int? y = GetNullableInt();
int? z = x + y;

the assignment to z effectively corresponds to:

int? z = x.HasValue && y.HasValue ? x.Value + y.Value : (int?)null;

Because an implicit conversion exists from a non-nullable value type to its nullable form, a lifted operator is applicable when just one operand is of a nullable type. The following example uses the same lifted + operator as the example above:

int? x = GetNullableInt();
int? y = x + 1;

If x is null, y is assigned null. Otherwise, y is assigned the value of x plus one.

The null propagating semantics of C#’s nullable conversions, lifted conversions, and lifted non-comparison operators are very similar to the corresponding conversions and operators in SQL. However, C#’s lifted comparison operators produce regular boolean results rather than introducing SQL’s three-valued boolean logic.


A comparison operator (==, !=, <, >, <=, >=) has a lifted form when the operand types are both non-nullable value types and the result type is bool. The lifted form of a comparison operator  is formed by adding a ? modifier to each operand type (but not to the result type). Lifted forms of the == and != operators consider two null values equal, and a null value unequal to a non-null value. Lifted forms of the <, >, <=, and >= operators return false if one or both operands are null.


When one of the operands of the == or != operator is the null literal, the other operand may be of any nullable type regardless of whether the underlying value type actually declares that operator. In cases where no operator == or != implementation is available, a check of the operand’s HasValue property is substituted. The effect of this rule is that statements such as

if (x == null) Console.WriteLine("x is null");
if (x != null) Console.WriteLine("x is non-null");

are permitted for an x of any nullable type or reference type, thus providing a common way of performing null checks for all types that can be null.


A new null coalescing operator, ??, is provided. The result of a ?? b is a if a is non-null; otherwise, the result is b. Intuitively, b supplies the value to use when a is null.


When a is of a nullable type and b is of a non-nullable type, a ?? b returns a non-nullable value, provided the appropriate implicit conversions exist between the operand types. In the example

int? x = GetNullableInt();
int? y = GetNullableInt();
int? z = x ?? y;
int i = z ?? -1;

the type of x ?? y is int?, but the type of z ?? -1 is int. The latter operation is particularly convenient because it removes the ? from the type and at the same time supplies the default value to use in the null case.


The null coalescing operator also works for reference types. The example

string s = GetStringValue();
Console.WriteLine(s ?? "Unspecified");

outputs the value of S, or outputs Unspecified if is null.

Visitors/Readers Comments
(for questions please use The Forum)



Appu

Hi I am Appu I don,t know these operators before viewing ur site.

  Thanks for Information

17/11/2007 03:36:28 UTC

Rullan
Thanx for that

29/07/2008 06:12:07 UTC




Add your Comments

Name:  
Message:
Note: For faster response please use Forums >> for your questions instead of the comments area! (Admin)