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

时间:2012-03-24 14:41:27

标签: c# .net linq null

我有以下Linq查询:

result.Partials.Where(o => o.IsPositive).Min(o => o.Result)

当result.Partials.Where(o => o.IsPositive)不包含元素时,我收到异常。有没有一种优雅的方法来处理这个,除了将操作分成两部分并检查null?我有一个像这样的操作课程。

编辑:问题与LINQ to Objects有关。

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

enter image description here

5 个答案:

答案 0 :(得分:58)

Min的计算的简短摘要

   var min = result.Partials.Where(o => o.IsPositive).Min(o => o.Result);

这是您的情况:如果没有匹配的元素,那么Min调用将引发异常(InvalidOperationException)。

 var min = result.Partials.Where(o => o.IsPositive)
                          .Select(o => o.Result)
                          .DefaultIfEmpty().Min();
当列表中没有元素时,

DefaultIfEmpty将在0元素上创建枚举。你怎么知道0是Min或0代表没有元素的列表?

   var min = result.Partials.Where(o => o.IsPositive)
                            .Min(o => (decimal?)o.Result);

这里min为null(defaul(decimal?))或实际的Min。所以这个结果的消费者会知道,如果结果为null,那么列表没有元素,当结果是十进制值时,列表中有一些元素,这些元素的Min就是那个值。

但是,如果这无关紧要,则可以调用min.GetValueOrDefault(0)

答案 1 :(得分:8)

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

result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min();

答案 2 :(得分:7)

如果序列为空,则无法使用Min(或Max)。如果不应该发生这种情况,那么您在定义result方面会遇到不同的问题。否则,您应检查序列是否为空并正确处理,例如:

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

由于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);
        }
    }
}

因此,如果集合具有值,则将计算Min(),否则将获得属性类型的默认值。

使用示例:

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
}

注意1 :您不需要检查This参数是否为空:被调用的Count()已经检查过该参数,并且它会引发与您相同的异常会抛出。

注意2 :仅在调用Count()方法便宜的情况下,此解决方案才有用。所有.NET集合都很好,因为它们都非常高效。对于特定的定制/非标准馆藏来说可能是个问题。