Partager via


Using Nullable Types (C# Programming Guide) 

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 exist 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.

This disparity can create extra programming work, with additional variables used to store state information, the use of special values, and so on. The nullable type modifier enables C# to create value-type variables that indicate an undefined value.

Examples of Nullable Types

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];

The Members of Nullable Types

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

    Value is of the same type as the underlying type. If HasValue is true, Value contains a meaningful value. If HasValue is false, accessing Value will throw a InvalidOperationException.

In this example, the HasValue member is used to test if the variable contains a value before attempting 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 like this:

int? y = 10;
if (y != null)
{
    System.Console.WriteLine(y.Value);
}
else
{
    System.Console.WriteLine("Undefined");
}

Explicit Conversions

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 x is null.
int m3 = n.Value;  // Compiles, but will create an exception if x is null.

If a user-defined conversion is defined between two data types, the same conversion can also be used with the nullable versions of these data types.

Implicit Conversions

A variable of nullable type can be set to null with the null keyword, as shown below:

int? n1 = null;

The conversion from an ordinary type to a nullable type, is implicit.

int? n2;
n2 = 10;  // Implicit conversion.

Operators

The predefined unary and binary operators and any user-defined operators that exist for value types may also be used by nullable types. 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 performing comparisons with nullable types, if either of the nullable types is null, the comparison is always evaluated to be false. It is therefore important not to assume that because a comparison is false, the opposite case is true. For example:

int? num1 = 10;
int? num2 = null;
if (num1 >= num2)
{
    System.Console.WriteLine("num1 is greater than or equal to num1");
}
else
{
    // num1 is NOT less than num2
}

The conclusion in the else statement above is not valid because num2 is null and therefore doesn't contain a value.

The ?? Operator

The ?? operator defines a default value that is returned when a nullable type is assigned to a non-nullable type.

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;

The bool? type

The bool? nullable type can contain three different values: true, false and null. As such, the cannot be used in conditionals such as with if, for, or while. For example, this code fails to compile with Compiler Error CS0266:

bool? b = null;
if (b) // Error CS0266.
{
}

This is not allows because it is unclear what null means in the context of a conditional. Nullable Booleans can be cast to a bool explicitly in order to be used in a conditional, but if the object has a value if null, InvalidOperationException will be thrown. It is therefore important to check the HasValue property before casting to bool.

Nullable Booleans are similar to the Boolean variable type used in SQL. To ensure that the results produced by the & and | operators are consistent with SQL's three-valued Boolean type, the following predefined operators are provided:

bool? operator &(bool? x, bool? y)

bool? operator |(bool? x, bool? y)

The results of these operators are listed in the table below:

X y x&y x|y

True

true

True

true

True

false

False

true

True

null

Null

true

False

true

False

true

False

false

False

false

False

null

False

null

Null

true

Null

true

Null

false

False

null

Null

null

Null

null

See Also

Reference

Boxing Nullable Types (C# Programming Guide)

Concepts

C# Programming Guide
Nullable Types (C# Programming Guide)