我有以下的Linq查询:
result.Partials.Where(o => o.IsPositive).Min(o => o.Result)
当result.Partials.Where(o => o.IsPositive)
不包含元素时,我会收到一个异常。除了将操作拆分为两部分并检查null之外,是否有更优雅的处理方式?我的类中充满了像这样的操作。
编辑:该问题与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
,还是代表一个空列表?
var min = result.Partials.Where(o => o.IsPositive)
.Min(o => (decimal?)o.Result);
这里的 Min
可能是空值(因为等同于 default(decimal?)
),或者是实际找到的最小值。
所以,这个结果的使用者将会知道:
null
时,列表没有任何元素Min
是返回值。然而,当这不重要时,可以调用 min.GetValueOrDefault(0)
。
null
值,那么获取到null
结果可能有两种情况:要么是集合没有元素,要么是给定属性的所有值都是null
。请注意,这里的翻译尽力保持了原文的意思和语气,并使用通俗易懂的方式表达。 - RudeyDefaultIfEmpty
方法来确保集合至少有一个项:result.Partials.Where(o => o.IsPositive).Select(o => o.Result).DefaultIfEmpty().Min();
o.Result
会导致抛出异常。 - Ritch Meltondecimal?
的文档,而不是通用情况。我会更新答案。 - Kendall Frey如果序列为空,则无法使用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集合都很好,因为它们都非常高效;对于特定的自定义/非标准集合可能会有问题。
Min()
而不是Sum()
。result
是什么? - JonMin()
方法而不是Where()
或Sum()
引起的。 - Kendall Frey