我有以下Linq查询:
result.Partials.Where(o => o.IsPositive).Min(o => o.Result)
当result.Partials.Where(o => o.IsPositive)不包含元素时,我收到异常。有没有一种优雅的方法来处理这个,除了将操作分成两部分并检查null?我有一个像这样的操作课程。
编辑:问题与LINQ to Objects有关。
这是我得到的例外(翻译后说:序列为空):
答案 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集合都很好,因为它们都非常高效。对于特定的定制/非标准馆藏来说可能是个问题。