C# 当使用Min或Max时,如何处理LINQ中的空值?

C# 当使用Min或Max时,如何处理LINQ中的空值?,c#,.net,linq,null,C#,.net,Linq,Null,我有以下Linq查询: result.Partials.Where(o => o.IsPositive).Min(o => o.Result) 当result.Partials.Where(o=>o.IsPositive)不包含元素时,会出现异常。除了将操作一分为二并检查null之外,还有什么优雅的方法来处理这个问题吗?我有一个像这样的操作类 编辑:该问题与LINQ到对象相关 这是我得到的例外(翻译为:序列为空): 如果序列为空,则不能使用Min(或Max)。如果不应该发生这种情况

我有以下Linq查询:

result.Partials.Where(o => o.IsPositive).Min(o => o.Result)
result.Partials.Where(o=>o.IsPositive)
不包含元素时,会出现异常。除了将操作一分为二并检查null之外,还有什么优雅的方法来处理这个问题吗?我有一个像这样的操作类

编辑:该问题与LINQ到对象相关

这是我得到的例外(翻译为:序列为空):


如果序列为空,则不能使用
Min
(或
Max
)。如果不应该发生这种情况,那么如何定义
结果
则是另一个问题。否则,应检查序列是否为空并进行适当处理,例如:

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...    

您可以使用
DefaultIfEmpty
方法确保集合中至少有一项:

result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min();
A
Min
-无调解(例外!) 这是您的情况:如果没有匹配的元素,则
Min
调用将引发异常(
invalidooperationexception

-使用
DefaultIfEmpty()
——仍然很麻烦 当列表中没有元素时,
DefaultIfEmpty
将在0元素上创建枚举。您如何知道0是
Min
,或者如果0表示没有元素的列表

-可为空的值;更好的解决方案 这里的
Min
要么为空(因为它等于
default(decimal?
),要么是找到的实际
Min

因此,该结果的消费者将知道:

  • 当结果为
    null
    时,列表中没有元素
  • 当结果是十进制值时,列表中有一些元素,这些元素的
    Min
    就是返回的值

  • 但是,如果这不重要,则可以调用
    min.GetValueOrDefault(0)

    在LINQ中表达它的另一种方法是使用:


    由于LINQ缺少像
    MinOrDefault()
    MaxOrDefault()
    这样的方法,您可以自己创建它们:

    public static class LinqExtensions
    {
        public static TProp MinOrDefault<TItem, TProp>(this IEnumerable<TItem> This, Func<TItem, TProp> selector)
        {
            if (This.Count() > 0)
            {
                return This.Min(selector);
            }
            else
            {
                return default(TProp);
            }
        }
    }
    
    注意1:您不需要检查
    参数是否为空:调用的
    Count()
    已经检查过了,并且它会引发与您将引发的相同的异常


    注意2:此解决方案仅适用于调用
    Count()
    方法成本较低的情况。所有.NET集合都很好,因为它们都非常高效;对于特定的定制/非标准系列,这可能是一个问题。

    您会遇到什么例外?根据我的经验,如果
    Partials
    为空,则应该得到0。堆栈跟踪调用了
    Min()
    而不是
    Sum()
    。结果是什么?对不起。我的错,操作是Min和Max而不是Sum。再次抱歉。编辑问题。您确定该行是引发异常的内容吗?异常是由
    Min()
    方法引发的,而不是
    Where()
    Sum()
    …如果默认值为null怎么办?@RitchMelton:我相信Min将返回null。我很确定使用null元素调用
    o.Result
    会导致引发异常。@Ritch:是的,当然。我读的是
    decimal?
    ,而不是一般情况下的文档。将更新答案。太笨拙了。我使用与Adrian Iftode建议的方法相同的方法-将所选字段强制转换为nullable我想添加以下内容:如果您的属性为nullable,并且源集合可以包含
    null
    值,则获得
    null
    结果可能意味着两件事:要么集合没有元素,或者给定属性的所有值均为
    null
     var min = result.Partials.Where(o => o.IsPositive)
                              .Select(o => o.Result)
                              .DefaultIfEmpty()
                              .Min();
    
       var min = result.Partials.Where(o => o.IsPositive)
                                .Min(o => (decimal?)o.Result);
    
    var min = result.Partials
        .Where(o => o.IsPositive)
        .Select(o => o.Result)
        .Aggregate(0, Math.Min); // Or any other value which should be returned for empty list
    
    public static class LinqExtensions
    {
        public static TProp MinOrDefault<TItem, TProp>(this IEnumerable<TItem> This, Func<TItem, TProp> selector)
        {
            if (This.Count() > 0)
            {
                return This.Min(selector);
            }
            else
            {
                return default(TProp);
            }
        }
    }
    
    public class Model
    {
        public int Result { get; set; }
    }
    
    // ...
    
    public void SomeMethod()
    {
        Console.WriteLine("Hello World");
        var filledList = new List<Model>
        {
            new Model { Result = 10 },
            new Model { Result = 9 },
        };
        var emptyList = new List<Model>();
        var minFromFilledList = filledList.MinOrDefault(o => o.Result)); // 9
        var minFromEmptyList = emptyList.MinOrDefault(o => o.Result)); // 0
    }