Net Q & A: how to avoid the exception thrown by max() on emptyenumerable?

Consultation area

Naor:

I have the following query:


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

If workers. Where (x = & gt; x. Companyid = = 8) if no workers are found, the above code will throw an exception.

Now the idea is: query can return 0 if it can't be found, but don't throw an exception. How can I modify the query above?

Answer area

Ron K.:

You can use the extension method of IEnumerable defaultifempty() to avoid this embarrassment. Refer to the following code.


    class Program
    {
        static void Main(string[] args)
        {
            List<Worker> Workers = new List<Worker>()
            {
                new Worker(){ CompanyId=1, CompanyName="tweet", ShoeSize=10 },
                new Worker(){ CompanyId=2, CompanyName="google", ShoeSize=20 },
            };

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

            Debug.WriteLine($"maxShoeSize={maxShoeSize}");
        }

    }

    class Worker
    {
        public int CompanyId { get; set; }

        public string CompanyName { get; set; }

        public int ShoeSize { get; set; }
    }

Output results:


maxShoeSize=0

Of course, the above 0 is not necessary. You can change it to any other number.

CptRobby:

Although the plan provided by the man upstairs can work normally, it doesn't look very eye-catching. It can be transformed into the following one.


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

Does the code look a little lengthy?The best way is to customize a extension method , as shown in the following code:


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

For simplicity, this extension only deals with the int type. You can change it to any type, such as: (long, double,...), and then you can continue to reform the caller.


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

I hope my answer can help more people.

Comment area

Xiaobian never dares to do Max on the empty collection , after all, it's not once or twice, so every time we judge whether there is a value in the collection in advance, and then execute Max , we didn't expect that there are magic extension methods defaultifempty and empty type that can help us to do it, and we all forget about sensory science????????????.


Read More: