Max return value if empty query

Solution 1:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                         .Select(x => x.ShoeSize)
                         .DefaultIfEmpty(0)
                         .Max();

The zero in DefaultIfEmpty is not necessary.

Solution 2:

I know this is an old question and the accepted answer works, but this question answered my question about whether such an empty set would result in an exception or a default(int) result.

The accepted answer however, while it does work, isn't the ideal solution IMHO, which isn't given here. Thus I am providing it in my own answer for the benefit of anyone who is looking for it.

The OP's original code was:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize);

This is how I would write it to prevent exceptions and provide a default result:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize as int?) ?? 0;

This causes the return type of the Max function to be int?, which allows the null result and then the ?? replaces the null result with 0.


EDIT
Just to clarify something from the comments, Entity Framework doesn't currently support the as keyword, so the way to write it when working with EF would be:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max<[TypeOfWorkers], int?>(x => x.ShoeSize) ?? 0;

Since the [TypeOfWorkers] could be a long class name and is tedious to write, I've added an extension method to help out.

public static int MaxOrDefault<T>(this IQueryable<T> source, Expression<Func<T, int?>> selector, int nullValue = 0)
{
    return source.Max(selector) ?? nullValue;
}

This only handles int, but the same could be done for long, double, or any other value type you need. Using this extension method is very simple, you just pass in your selector function and optionally include a value to be used for null, which defaults to 0. So the above could be rewritten like so:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).MaxOrDefault(x => x.ShoeSize);

Hopefully that helps people out even more.

Solution 3:

Max() won't return anything in that case.

It will raise InvalidOperationException since the source contains no elements.

Solution 4:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                     .Select(x => x.ShoeSize)
                     .DefaultIfEmpty()
                     .Max();

Solution 5:

If this is Linq to SQL, I don't like to use Any() because it results in multiple queries to SQL server.

If ShoeSize is not a nullable field, then using just the .Max(..) ?? 0 will not work but the following will:

int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0;

It absolutely does not change the emitted SQL, but it does return 0 if the sequence is empty because it changes the Max() to return an int? instead of an int.