Read the syntax
With nullable analysis enabled, string is intended to be non-null and string? may be null; the compiler reports warnings, not runtime validation guarantees.
?? chooses a fallback, ?. stops member access on null, and ??= assigns only when the left side is null. Check uncertain values before dereferencing them.
Syntax
string? maybeNull = null;\nvar result = value ?? defaultValue;Examples
Nullable vs Non-Nullable Reference Types
With nullable reference types enabled, the compiler warns if a non-nullable reference might be null.
#nullable enable
string name = "John"; // never null (compiler-enforced, with warnings on violation)
string? nickname = null; // explicitly allowed to be null
Console.WriteLine(name.Length); // safe, no warning
// Console.WriteLine(nickname.Length); // compiler WARNING - could be null
if (nickname != null)
{
Console.WriteLine(nickname.Length); // safe now, compiler knows it's checked
}- With nullable reference types enabled, the compiler warns if a non-nullable reference might be null.
- With nullable analysis enabled, string is intended to be non-null and string? may be null; the compiler reports warnings, not runtime validation guarantees.
- name.Length prints 4. nickname is null, so the guarded block does not run; uncommenting the unguarded dereference triggers a nullable warning.
Null-Coalescing Operator (??)
Providing a fallback value when something might be null, in a single concise expression.
string? input = null;
string result = input ?? "default value";
Console.WriteLine(result); // default value
int? maybeAge = null;
int age = maybeAge ?? 0;
Console.WriteLine(age); // 0- Providing a fallback value when something might be null, in a single concise expression.
- With nullable analysis enabled, string is intended to be non-null and string? may be null; the compiler reports warnings, not runtime validation guarantees.
- Both left operands are null, so ?? selects default value and 0. The two lines print those fallback values.
Null-Conditional Operator (?.)
Safely accessing a member only if the object isn't null, short-circuiting to null instead of throwing.
Person p = new Person(); // p.Home is null
string? city = p.Home?.City; // null, instead of a NullReferenceException
Console.WriteLine(city ?? "No address on file");
int? length = p.Home?.City?.Length; // chains safely through multiple levels
class Address { public string City = ""; }
class Person { public Address? Home; }- Safely accessing a member only if the object isn't null, short-circuiting to null instead of throwing.
- With nullable analysis enabled, string is intended to be non-null and string? may be null; the compiler reports warnings, not runtime validation guarantees.
- Home is null; ?. yields null instead of dereferencing it. The fallback prints No address on file, and length remains nullable.
Null-Coalescing Assignment (??=)
Assigning a value only if the variable is currently null.
List<string>? names = null;
names ??= new List<string>(); // only assigns if names is currently null
names.Add("John");
Console.WriteLine(string.Join(", ", names));- Assigning a value only if the variable is currently null.
- With nullable analysis enabled, string is intended to be non-null and string? may be null; the compiler reports warnings, not runtime validation guarantees.
- Because names starts null, ??= creates a list once. Add stores John, and Join prints John.
Best practices
- Enable nullable reference types (<Nullable>enable</Nullable> in the project file) for new projects - it catches a huge class of NullReferenceException bugs at compile time
- Use ?. and ?? together (obj?.Property ?? defaultValue) for concise, safe access with a fallback in a single expression
- Use ??= to lazily initialize a variable only if it is currently null, instead of a longer explicit if check
- Treat compiler nullable warnings seriously rather than suppressing them with ! (the null-forgiving operator) unless you are certain a value cannot actually be null at that point
Runtime & versions
.NET runtime. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
C# language reference