Handling Null Values in LINQ Projections in C
Handling null values during LINQ projections is essential for writing
robust C# code that avoids runtime NullReferenceException
errors. When transforming collections or database query results into new
data shapes using .Select(), source objects or their nested
navigation properties may be null. This article covers the
primary techniques used to handle null values safely during LINQ
projections, including null-conditional operators, null-coalescing
fallbacks, conditional expressions, and proper handling of outer
joins.
The Null-Conditional Operator
(?.)
The null-conditional operator allows you to access members of an object only if that object is not null. If the object is null, the expression evaluates to null instead of throwing an exception.
var userViewModels = users.Select(u => new UserViewModel
{
Id = u.Id,
City = u.Address?.City
}).ToList();If u.Address is null, u.Address?.City
safely resolves to null. Note that if the projected
property is a non-nullable value type (like an int), the
null-conditional operator turns the result into a nullable type
(int?).
The Null-Coalescing Operator
(??)
To provide a default value when a property or nested property is
null, combine the null-conditional operator with the null-coalescing
operator (??):
var userViewModels = users.Select(u => new UserViewModel
{
Id = u.Id,
City = u.Address?.City ?? "Unknown",
PostalCode = u.Address?.PostalCode ?? 0
}).ToList();If u.Address or City is null,
"Unknown" is assigned. This approach prevents downstream
code from having to check for null strings or missing values.
Ternary Conditional Expressions
When projection logic requires complex condition checking or
alternative object instantiation, a ternary expression
(condition ? then : else) provides explicit control:
var userViewModels = users.Select(u => new UserViewModel
{
Id = u.Id,
AddressSummary = u.Address != null
? $"{u.Address.Street}, {u.Address.City}"
: "No Address Provided"
}).ToList();This ensures the string interpolation only executes when the underlying object exists.
Handling Nulls in GroupJoins and Left Outer Joins
When performing left outer joins using LINQ's GroupJoin
and DefaultIfEmpty, elements from the right side of the
join will be null if no match exists. You must account for these nulls
inside the final projection:
var query = from user in users
join order in orders on user.Id equals order.UserId into userOrders
from order in userOrders.DefaultIfEmpty()
select new UserOrderDto
{
UserId = user.Id,
UserName = user.Name,
OrderId = order != null ? order.Id : (int?)null,
OrderTotal = order?.Total ?? 0m
};Using DefaultIfEmpty() provides a sequence with a single
null element when no matching records exist, making the
order != null check mandatory.
LINQ to Entities vs. LINQ to Objects
Be aware of where your LINQ query executes:
- LINQ to Objects (In-Memory): Evaluates strictly in
C#. Accessing a property on a null object immediately throws a
NullReferenceExceptionunless guarded by?.or conditional checks. - LINQ to Entities (EF Core / Database): Translates
expressions into SQL. SQL handles nulls via
LEFT JOINsemantics and returnsNULLwithout throwing errors. However, once the query projects into in-memory types or uses client-side evaluation, null handling must still conform to standard C# rules to prevent mapping issues.