簡體   English   中英

使用 Min 或 Max 時如何處理 LINQ 中的空值?

[英]How to handle nulls in LINQ when using Min or Max?

我有以下 Linq 查詢:

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

result.Partials.Where(o => o.IsPositive)不包含元素時,我得到一個異常。 除了將操作一分為二並檢查是否為空之外,是否有一種優雅的方法來處理這個問題? 我有一堂課充滿了這樣的操作。

編輯:問題與 LINQ to Objects 有關。

這是我得到的異常(翻譯它說:序列為空):

在此處輸入圖片說明

Min計算的簡短摘要

- 沒有調解(例外!)

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

這是您的情況:如果沒有匹配的元素,則Min調用將引發異常( InvalidOperationException )。

- 使用DefaultIfEmpty() -- 仍然很麻煩

 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 (因為它等於default(decimal?) )要么是實際找到的Min

所以這個結果的消費者會知道:

  1. 當結果為null ,列表沒有元素
  2. 當結果是十進制值時,列表有一些元素,這些元素的Min是返回值。

但是,當這無關緊要時,可以調用min.GetValueOrDefault(0)

您可以使用DefaultIfEmpty方法來確保集合至少有 1 個項目:

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

如果序列為空,則不能使用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...    

在 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

由於 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 集合都很好,因為它們都非常高效; 對於特定的定制/非標准集合,這可能是一個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM