Nullable types are represented by the Nullable<T> structure. An instance of Nullable<T> is boxed to either a null reference (if it doesn't have a value) or a boxed value of T (if it does).
The type parameter T has a value type constraint specified e.g., struct Nullable<T> where T : struct
// Implicit conversion from T to Nullable<T> (wrapping). int? n1 = 8; Nullable<int> n2 = 8; // Nullable constructors. var n3 = new Nullable<int>(); // n3 == null var n4 = new Nullable<int>(8); // n4 == 8 // All three values x1, x2, and x3 are null. int? x1 = new int?(); int? x2 = default(int?); int? x3 = (int?)null;
int? n = 8; // Explicit conversion from Nullable<T> to T (unwrapping). int i1 = (int)n; // the same as n.Value // Check if a nullable variable has a value. if (n == null) { } if (n.HasValue) { } // Use the 'is' and 'as' operators. if (n is Int32) { } int? m = n as Int32?; // Use Nullable<T>.GetValueOrDefault() int? n1 = 8; int i1 = n1.GetValueOrDefault(); // 8 int i2 = n1.GetValueOrDefault(88); // 8 int? n2 = null; int i3 = n2.GetValueOrDefault(); // 0 int i4 = n2.GetValueOrDefault(88); // 88
The truth table for bool? variables determined by the C# compiler:
bool? x; bool? y;
x | y | x & y | x | y | x ^ y | !x |
---|---|---|---|---|---|
true | true | true | true | false | false |
true | false | false | true | true | false |
true | null | null | true | null | false |
false | true | false | true | true | true |
false | false | false | false | false | true |
false | null | false | null | null | true |
null | true | null | true | null | null |
null | false | false | null | null | null |
null | null | null | null | null | null |
C# 8.0 introduced nullable and non-nullable reference types. Reference types can be configured to no longer allow the null value by setting a file- or project-level option.
Enable the feature at the project level:
<PropertyGroup> <Nullable>enable</Nullable> </PropertyGroup>
Disable the feature at the file level:
#nullable disable
Enable the feature at the file level:
#nullable enable
Example of using a nullable reference type. Note that non-nullable fields (FirstName and LastName) have to have a value assigned:
#nullable enable ... class PersonName { public string FirstName = String.Empty; public string? MiddleName; // a nullable reference field public string LastName = String.Empty; }
Use the null-conditional operator to check if a member variable might be null
:
var person = new PersonName(); ... // If the MiddleName field is null, the variable 'len' will be assigned null. int? len = person.MiddleName?.Length;
Use the null-coalescing operator to assign an alternative value if a variable is null
:
var person = new PersonName(); ... // If the MiddleName field is null, the variable 'len' will have the value of 2. int len = person.MiddleName?.Length ?? 2;