title | description | ms.date | helpviewer_keywords | |
---|---|---|---|---|
Nullable value types - C# reference |
Learn about C# nullable value types and how to use them |
11/04/2019 |
|
A nullable value type T?
represents all values of its underlying value type T
and an additional null value. For example, you can assign any of the following three values to a bool?
variable: true
, false
, or null
. An underlying value type T
cannot be a nullable value type itself.
Any nullable value type is an instance of the generic xref:System.Nullable%601?displayProperty=nameWithType structure. You can refer to a nullable value type with an underlying type T
in any of the following interchangeable forms: Nullable<T>
or T?
.
You typically use a nullable value type when you need to represent the undefined value of an underlying value type. For example, a Boolean, or bool
, variable can only be either true
or false
. However, in some applications a variable value can be undefined or missing. For example, a database field may contain true
or false
, or it may contain no value at all, that is, NULL
. You can use the bool?
type in that scenario.
As a value type is implicitly convertible to the corresponding nullable value type, you can assign a value to a variable of a nullable value type as you would do that for its underlying value type. You can also assign the null
value. For example:
[!code-csharpdeclare and assign]
The default value of a nullable value type represents null
, that is, it's an instance whose xref:System.Nullable%601.HasValue%2A?displayProperty=nameWithType property returns false
.
You can use the is
operator with a type pattern to both examine an instance of a nullable value type for null
and retrieve a value of an underlying type:
[!code-csharp-interactiveuse pattern matching]
You always can use the following read-only properties to examine and get a value of a nullable value type variable:
-
xref:System.Nullable%601.HasValue%2A?displayProperty=nameWithType indicates whether an instance of a nullable value type has a value of its underlying type.
-
xref:System.Nullable%601.Value%2A?displayProperty=nameWithType gets the value of an underlying type if xref:System.Nullable%601.HasValue%2A is
true
. If xref:System.Nullable%601.HasValue%2A isfalse
, the xref:System.Nullable%601.Value%2A property throws an xref:System.InvalidOperationException.
The following example uses the HasValue
property to test whether the variable contains a value before displaying it:
[!code-csharp-interactiveuse HasValue]
You can also compare a variable of a nullable value type with null
instead of using the HasValue
property, as the following example shows:
[!code-csharp-interactiveuse comparison with null]
If you want to assign a value of a nullable value type to a non-nullable value type variable, you might need to specify the value to be assigned in place of null
. Use the null-coalescing operator ??
to do that (you can also use the xref:System.Nullable%601.GetValueOrDefault(%600)?displayProperty=nameWithType method for the same purpose):
[!code-csharp-interactive?? operator]
If you want to use the default value of the underlying value type in place of null
, use the xref:System.Nullable%601.GetValueOrDefault?displayProperty=nameWithType method.
You can also explicitly cast a nullable value type to a non-nullable type, as the following example shows:
[!code-csharpexplicit cast]
At run time, if the value of a nullable value type is null
, the explicit cast throws an xref:System.InvalidOperationException.
A non-nullable value type T
is implicitly convertible to the corresponding nullable value type T?
.
The predefined unary and binary operators or any overloaded operators that are supported by a value type T
are also supported by the corresponding nullable value type T?
. These operators, also known as lifted operators, produce null
if one or both operands are null
; otherwise, the operator uses the contained values of its operands to calculate the result. For example:
[!code-csharplifted operators]
Note
For the bool?
type, the predefined &
and |
operators don't follow the rules described in this section: the result of an operator evaluation can be non-null even if one of the operands is null
. For more information, see the Nullable Boolean logical operators section of the Boolean logical operators article.
For the comparison operators <
, >
, <=
, and >=
, if one or both operands are null
, the result is false
; otherwise, the contained values of operands are compared. Do not assume that because a particular comparison (for example, <=
) returns false
, the opposite comparison (>
) returns true
. The following example shows that 10 is
- neither greater than or equal to
null
- nor less than
null
[!code-csharp-interactiverelational and equality operators]
For the equality operator ==
, if both operands are null
, the result is true
, if only one of the operands is null
, the result is false
; otherwise, the contained values of operands are compared.
For the inequality operator !=
, if both operands are null
, the result is false
, if only one of the operands is null
, the result is true
; otherwise, the contained values of operands are compared.
If there exists a user-defined conversion between two value types, the same conversion can also be used between the corresponding nullable value types.
An instance of a nullable value type T?
is boxed as follows:
- If xref:System.Nullable%601.HasValue%2A returns
false
, the null reference is produced. - If xref:System.Nullable%601.HasValue%2A returns
true
, the corresponding value of the underlying value typeT
is boxed, not the instance of xref:System.Nullable%601.
You can unbox a boxed value of a value type T
to the corresponding nullable value type T?
, as the following example shows:
[!code-csharp-interactiveboxing and unboxing]
The following example shows how to determine whether a xref:System.Type?displayProperty=nameWithType instance represents a constructed nullable value type, that is, the xref:System.Nullable%601?displayProperty=nameWithType type with a specified type parameter T
:
[!code-csharp-interactivewhether Type is nullable]
As the example shows, you use the typeof operator to create a xref:System.Type?displayProperty=nameWithType instance.
If you want to determine whether an instance is of a nullable value type, don't use the xref:System.Object.GetType%2A?displayProperty=nameWithType method to get a xref:System.Type instance to be tested with the preceding code. When you call the xref:System.Object.GetType%2A?displayProperty=nameWithType method on an instance of a nullable value type, the instance is boxed to xref:System.Object. As boxing of a non-null instance of a nullable value type is equivalent to boxing of a value of the underlying type, xref:System.Object.GetType%2A returns a xref:System.Type instance that represents the underlying type of a nullable value type:
[!code-csharp-interactiveGetType example]
Also, don't use the is operator to determine whether an instance is of a nullable value type. As the following example shows, you cannot distinguish types of a nullable value type instance and its underlying type instance with the is
operator:
[!code-csharp-interactiveis operator example]
Instead use the xref:System.Nullable.GetUnderlyingType%2A?displayProperty=nameWithType from the first example and typeof operator to check if an instance is of a nullable value type.
Note
The methods described in this section are not applicable in the case of nullable reference types.
For more information, see the following sections of the C# language specification:
- Nullable types
- Lifted operators
- Implicit nullable conversions
- Explicit nullable conversions
- Lifted conversion operators
- What exactly does 'lifted' mean?
- xref:System.Nullable%601?displayProperty=nameWithType
- xref:System.Nullable?displayProperty=nameWithType
- xref:System.Nullable.GetUnderlyingType%2A?displayProperty=nameWithType
- Nullable reference types