C# Nullable Types at Depth
A nullable value type holds a value or holds no value at all. Its members and operators read that state, supply a default, and assign only when the value is missing.
Reading the state with HasValue
The nullable int starts empty. Assignment fills it, and HasValue reports the change.
using System;
class Program
{
static void Main(string[] args)
{
int? maybe = null;
Console.WriteLine(maybe.HasValue);
Console.WriteLine(maybe.GetValueOrDefault());
maybe = 12;
Console.WriteLine(maybe.HasValue);
}
}Assigning once with ??=
The first ??= fills the empty value. The second ??= runs while a value exists, so it assigns nothing.
using System;
class Program
{
static void Main(string[] args)
{
int? maybe = null;
maybe ??= 7;
Console.WriteLine(maybe);
maybe ??= 9;
Console.WriteLine(maybe);
}
}The null-forgiving operator
The ! operator promises the compiler that the value is safe to use as a plain string. The value itself is still null, and the comparison proves it.
using System;
#nullable enable
class Program
{
static void Main(string[] args)
{
string? name = null;
string sure = name!;
Console.WriteLine(sure == null);
}
}Example
using System;
class Program
{
static void Main(string[] args)
{
int? score = null;
score ??= 40;
Console.WriteLine(score);
Console.WriteLine(score.HasValue);
}
}Key points
- HasValue reports whether a nullable value type currently holds a value.
- GetValueOrDefault() returns the held value when one exists.
- GetValueOrDefault() returns the type default, such as 0 for int, when the value is null.
- The ??= operator assigns its right side only when the left side is null.
- A second ??= leaves an existing value unchanged.
- The null-forgiving operator ! tells the compiler to treat an expression as not null.
- The ! operator changes nothing at runtime. The underlying value stays exactly as it was.
In this example, the score starts as null. The ??= operator assigns 40 because no value exists yet. The prints show the stored value and HasValue reporting true.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A nullable int already holds 7. What happens when `maybe ??= 9;` runs?