• 如何避免在 EmptyEnumerable 上执行 Max() 抛出的异常 ?
  • 发布于 2个月前
  • 541 热度
    0 评论
  • Cactus
  • 21 粉丝 62 篇博客
  •   
咨询区
Naor:
我有下面的一个查询:
int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                          .Max(x => x.ShoeSize);
如果 Workers.Where(x => x.CompanyId == 8) 没有查到任何 Workers 的话,上面的代码将会抛出异常。
现在的想法是:查不到的话 query 可以返回 0,但千万不要抛异常,我该如何修改上面的 query 呢?
回答区
Ron K.:
可以用 IEnumerable 的扩展方法 DefaultIfEmpty() 来避免这种尴尬,参考如下代码。
    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; }
    }
输出结果:
maxShoeSize=0
当然上面的 0 不是必须的,你可以改成其他的任何数。
CptRobby:
楼上那哥们提供的方案虽然可以正常运行,但看起来不是很入眼,可以改造成下面这样。
    int maxShoeSize = Workers.Where(x => x.CompanyId == 8)
                             .Select(x => (int?)x.ShoeSize)
                              .Max() ?? 0;
代码看起来是不是有点冗长,最好的方式还是自定义一个 扩展方法,如下代码所示:
public static int MaxOrDefault<T>(this IQueryable<T> source, Expression<Func<T, int?>> selector, int nullValue = 0)
{
    return source.Max(selector) ?? nullValue;
}

为了简单,这个扩展方法仅处理了 int 类型,你可以改成任意类型如:(long,double,...),接下来可以继续改造一下调用方。

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

希望我的答案可以帮助到更多人。
点评区
小编从来不敢在 Empty Collection 上做 Max,毕竟被坑的不是一次两次了,所以每次都提前判断集合是否存在值再执行 Max,没想到还有神奇的扩展方法 DefaultIfEmpty 和 可空类型 可以帮忙搞定,感觉学的都忘了
用户评论