How to handle nulls in LINQ when using Min or Max?
You can use the DefaultIfEmpty
method to ensure the collection has at least 1 item:
result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min();
A short summary of the calculation of a Min
- No mediation (Exception!)
var min = result.Partials.Where(o => o.IsPositive).Min(o => o.Result);
This is your case: if there are no matching elements, then the Min
call will raise an exception (InvalidOperationException
).
- With DefaultIfEmpty()
-- still troublesome
var min = result.Partials.Where(o => o.IsPositive)
.Select(o => o.Result)
.DefaultIfEmpty()
.Min();
DefaultIfEmpty
will create an enumeration over the 0 element, when there are no elements in the list. How do you know that 0 is the Min
or if 0 stands for a list with no elements?
- Nullable values; A better solution
var min = result.Partials.Where(o => o.IsPositive)
.Min(o => (decimal?)o.Result);
Here Min
is either null (because that's equal to default(decimal?)
) or the actual Min
found.
So a consumer of this result will know that:
- When result is
null
then the list had no elements - When the result is a decimal value then the list had some elements and the
Min
of those elements is that returned value.
However, when this doesn't matter, then min.GetValueOrDefault(0)
can be called.
You can't use Min
(or Max
) if the sequence is empty. If that shouldn't be happening, you have a different issue with how you define result
. Otherwise, you should check if the sequence is empty and handle appropriately, eg:
var query = result.Partials.Where(o => o.IsPositve);
min = query.Any() ? query.Min(o => o.Result) : 0; // insert a different "default" value of your choice...