Question

What the ?? Operator Means in C#

csharpnull-coalescing-operator

Question

I came across this line of C# code:

CopyFormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

What does the ?? operator mean in this context? Is it a kind of ternary operator?

I am also finding it difficult to search for because two question marks are hard to look up directly.

Short Answer

By the end of this page, you will understand what the ?? operator does in C#, why it is called the null-coalescing operator, and how it helps you provide a fallback value when something is null. You will also see how it compares to the ternary operator, how it is used in real codebases, and what common mistakes to avoid.

Concept

The ?? operator in C# is called the null-coalescing operator.

It is used to choose a fallback value when the expression on the left is null.

Core idea

result = leftValue ?? fallbackValue;

This means:

  • If leftValue is not null, use it.
  • If leftValue is null, use fallbackValue.

So this code:

CopyFormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

means:

  • If formsAuth already has an object, assign that object to CopyFormsAuth.
  • Otherwise, create a new FormsAuthenticationWrapper and assign that instead.

Why this matters

In real programs, values are often optional or missing:

  • a method parameter may not be provided
  • a configuration value may be absent
  • a database field may be null
  • an object may not have been created yet

The ?? operator lets you handle those cases clearly and compactly.

Equivalent longer form

The same logic can be written like this:

if (formsAuth != null)
{
    CopyFormsAuth = formsAuth;
}
else
{
    CopyFormsAuth = new FormsAuthenticationWrapper();
}

Or with a ternary operator:

CopyFormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

The ?? version is shorter and specifically designed for null checks.

Mental Model

Think of ?? as a backup choice operator.

Imagine you are trying to sit in your assigned chair:

  • If your chair is available, sit there.
  • If your chair is missing, use the spare chair.

That is exactly what ?? does:

chairToUse = assignedChair ?? spareChair;

Another way to think about it:

  • left side = your first choice
  • right side = your backup plan

If the first choice exists, use it. If not, use the backup.

Take Quiz

Syntax and Examples

Basic syntax

value = possibleNullValue ?? fallbackValue;

Example 1: String fallback

string name = null;
string displayName = name ?? "Guest";

Console.WriteLine(displayName);

Output:

Guest

Because name is null, C# uses "Guest".

Example 2: Existing value is kept

string name = "Ava";
string displayName = name ?? "Guest";

Console.WriteLine(displayName);

Output:

Ava

Because name is not null, the fallback is ignored.

Example 3: Objects

User currentUser = null;
User userToDisplay = currentUser ?? new User();

If currentUser is null, a new User object is created.

Example 4: Method return fallback

string GetTitle()
{
    return null;
}

string title = GetTitle() ?? "Untitled";

This is very common when a method might return null.

Related operator: ??=

C# also has the null-coalescing assignment operator:

settings ??= new AppSettings();

This means:

  • If settings is null, assign a new AppSettings() to it.
  • Otherwise, leave it unchanged.

Step by Step Execution

Consider this code:

string inputName = null;
string finalName = inputName ?? "Guest";

Console.WriteLine(finalName);

Here is what happens step by step:

  1. inputName is created and set to null.
  2. C# evaluates inputName ?? "Guest".
  3. It checks the left side: inputName.
  4. Because inputName is null, C# uses the right side: "Guest".
  5. finalName becomes "Guest".
  6. Console.WriteLine(finalName); prints Guest.

Now look at this version:

string inputName = "Mina";
string finalName = inputName ?? "Guest";

Console.WriteLine(finalName);

Step by step:

  1. inputName is set to "Mina".
  2. C# evaluates inputName ?? "Guest".
  3. It checks the left side.
  4. Because inputName is not null, C# keeps that value.
  5. The right side is not needed.
  6. finalName becomes "Mina".
  7. The program prints Mina.

Important behavior

The right side is only used if the left side is null.

That means code like this avoids unnecessary work:

User user = existingUser ?? CreateDefaultUser();

CreateDefaultUser() only matters when existingUser is null.

Real World Use Cases

Default values for optional data

string theme = savedTheme ?? "light";

If a user has not chosen a theme yet, the app uses "light".

Dependency fallback

_logger = logger ?? new ConsoleLogger();

If no logger is provided, use a default one.

Configuration values

string connectionString = configValue ?? "Server=localhost;Database=AppDb;";

Useful when configuration is missing in development.

API or database values

string city = customer.City ?? "Unknown";

If the database field is null, show a safe display value.

Constructor initialization

public ReportService(IFormatter formatter)
{
    _formatter = formatter ?? new DefaultFormatter();
}

This pattern is common in dependency injection and testable code.

Take Quiz

Real Codebase Usage

In real projects, developers use ?? to make null-handling shorter and easier to read.

Common patterns

1. Constructor defaults

public MyService(ICache cache)
{
    _cache = cache ?? new MemoryCache();
}

This gives the class a working dependency even if none is passed in.

2. Guarding optional return values

var name = repository.GetDisplayName(userId) ?? "Anonymous";

This avoids extra if statements.

3. Safe model preparation

viewModel.Title = article.Title ?? "Untitled";

Useful when preparing data for UI output.

4. Chaining with null-aware code

string zip = customer?.Address?.ZipCode ?? "No ZIP";

This combines:

  • ?. to safely access nested members
  • ?? to provide a fallback if the result is null

5. Lazy initialization with ??=

_items ??= new List<string>();

This is common when a list or cache should only be created when first needed.

Why teams like it

  • less boilerplate
  • clearer intent
  • fewer manual null checks
  • easier-to-read constructors and assignments

Common Mistakes

Mistake 1: Thinking ?? checks for false or empty values

?? only checks for null.

It does not treat these as null:

  • false
  • 0
  • "" (empty string)

Example

string text = "";
string result = text ?? "default";

Console.WriteLine(result);

Output is an empty string, not default.

If you want to treat empty strings specially, use something like:

string result = string.IsNullOrEmpty(text) ? "default" : text;

Mistake 2: Confusing ?? with the ternary operator

Broken understanding:

// This is not what ?? means
value = condition ?? option1 : option2;

?? is not a general condition operator.

Use:

  • ?? for null fallback
  • ?: for true/false branching

Mistake 3: Forgetting the left side must be nullable or a reference type

?? is used when the left expression can be null.

For example:

int? count = null;
int finalCount = count ?? 0;

This works because count is int?, not plain int.

Mistake 4: Overusing ?? when explicit validation is clearer

Sometimes a value being null should be treated as an error, not replaced silently.

// Sometimes too silent
_connection = connection ?? new DatabaseConnection();

In some designs, this may hide a bug. You may want:

_connection = connection ?? throw new ArgumentNullException(nameof(connection));

Mistake 5: Assuming the fallback always runs

var result = existingValue ?? CreateValue();

CreateValue() is only used if existingValue is null.

Comparisons

ConceptPurposeExampleBest when
??Use a fallback if a value is nullname ?? "Guest"You only care about null
?:Choose between two values based on a conditionage >= 18 ? "Adult" : "Minor"You need true/false logic
if/elseFull branching logicif (x == null) ...Logic is more complex or needs multiple steps
??=Assign only if current value is nulllist ??= new List<int>()Lazy initialization

?? vs ternary operator

These are similar in result but different in meaning:

string result = name ?? "Guest";

Equivalent ternary form:

string result = name != null ? name : "Guest";

The ternary operator is more general. The null-coalescing operator is specialized for null checks.

?? vs string.IsNullOrEmpty

string result = text ?? "default";

Only handles null.

string result = string.IsNullOrEmpty(text) ? "default" : text;

Handles both null and "".

?? vs null-conditional operator ?.

  • ?. safely accesses a member if the object is not null
  • ?? supplies a fallback if the result is null

Example:

string city = user?.Address?.City ?? "Unknown";

This means:

  • try to get user.Address.City
  • if anything becomes null along the way, use "Unknown"
Take Quiz

Cheat Sheet

Quick syntax

value = possibleNull ?? fallback;

Meaning

  • left side not null -> use left side
  • left side null -> use right side

Example

string name = null;
string display = name ?? "Guest";

Equivalent code

string display = name != null ? name : "Guest";

Common uses

  • default constructor arguments
  • fallback strings
  • optional configuration values
  • object initialization
  • nullable value types

Works with

  • reference types
  • nullable value types like int?, bool?, DateTime?

Does not check

  • empty string ""
  • 0
  • false

Related operators

obj?.Name      // safe member access
settings ??= new Settings(); // assign if null

Example with nullable value type

int? score = null;
int finalScore = score ?? 0;

FAQ

What does ?? mean in C#?

It is the null-coalescing operator. It returns the left value if it is not null; otherwise, it returns the right value.

Is ?? the same as the ternary operator?

No. The ternary operator ?: works with any boolean condition. ?? is specifically for null fallback.

Does ?? work with empty strings?

No. An empty string is not null. Use string.IsNullOrEmpty() if you want to handle both.

Can I use ?? with integers in C#?

Yes, if the integer is nullable, such as int?. A plain int cannot be null.

What is ??= in C#?

It is the null-coalescing assignment operator. It assigns a value only if the variable is currently null.

Why is ?? useful in constructors?

It lets you provide a default dependency or value when an argument is null, keeping constructor code short and readable.

Can ?? be combined with ?.?

Yes. This is very common for safe navigation plus a fallback value.

string name = user?.Profile?.DisplayName ?? "Anonymous";
Take Quiz

Mini Project

Description

Build a small C# console program that displays a user's nickname if one exists, or a default value if it does not. This demonstrates how the null-coalescing operator simplifies fallback logic in a practical program.

Goal

Create a program that safely handles missing values by using ?? to provide defaults.

Requirements

  • Create a nullable or reference-type variable that may contain null
  • Use the ?? operator to provide a fallback value
  • Print the final result to the console
  • Add a second example where the original value is not null
Take Quiz

Keep learning

Related questions

View more