1

我有一个简单的单行 linq 查询来查找列表中包含最高属性值的项目,并且仅当有一定数量的项目符合此条件时才使用它们创建一个新列表。例如:

List<MyObject> objects = new List<MyObject>()
{
    new MyObject() { MyValue = 6 },
    new MyObject() { MyValue = 7 },
    new MyObject() { MyValue = 7 },
    new MyObject() { MyValue = 8 },
    new MyObject() { MyValue = 8 },
};

int countRequired = 2;

List<MyObject> highestValue2Required = objects.GroupBy( o => o.MyValue )
    .OrderByDescending( g => g.Key )
    .Where( g => g.Count() == countRequired )
    .FirstOrDefault()
    .ToList();

如果我的列表中有满足这些条件的数据,将创建一个新列表,其中包含 的两个实例MyObject,即 where 的实例MyValue = 8

但是,如果没有符合条件的数据,我会遇到异常,因为IGrouping查询的结果为空,并且调用ToList()它不起作用。例如:

int countRequired = 3;

List<MyObject> highestValue3Required = objects.GroupBy( o => o.MyValue )
    .OrderByDescending( g => g.Key )
    .Where( g => g.Count() == countRequired )
    .FirstOrDefault()
    .ToList();

因为MyObject列表中只有两个实例MyValue等于最大值(即 8),所以查询抛出异常

System.ArgumentNullException: 'Value cannot be null.


是否可以使用此空值在我的“单行”查询中返回一个空列表?

这样做的明显方法是删除ToList()调用并简单地返回IGrouping结果,并且仅ToList()在它不为空时调用,但我很好奇它是否可以内联完成。

4

2 回答 2

1

调用FirstOrDefault(). _ 如果此方法返回null,则整个表达式的结果将为空。然后,您可以使用null 合并运算符null结果转换为空列表。

var highestValue3Required = objects.GroupBy( o => o.MyValue )
    .OrderByDescending( g => g.Key )
    .Where( g => g.Count() == countRequired )
    .FirstOrDefault()
    ?.ToList() ?? new List<MyObject>();
于 2019-03-14T00:49:11.697 回答
1

问题出在.FirstOrDefault().ToList(). 由于FirstOrDefault()可能返回一个值或 NULL,您不能直接调用.ToList().

如果您希望最终结果null是没有匹配项,您可以简单地?在调用中添加一个空调节器 ( ) FirstOrDefault()

List<MyObject> highestValue2Required = objects.GroupBy(o => o.MyValue)
    .OrderByDescending(g => g.Key)
    .Where(g => g.Count() == countRequired)
    .FirstOrDefault()?
    .ToList();

但是,如果您对 null 值不满意,并且想要一个空列表,则可以将以下扩展方法添加到您的项目中,以便能够使用单行:

static class Extensions
{
    public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> source)
    {
        return (source ?? Enumerable.Empty<T>());
    }
}

现在,您可以轻松地执行以下操作:

List<MyObject> highestValue2Required = objects.GroupBy(o => o.MyValue)
    .OrderByDescending(g => g.Key)
    .Where(g => g.Count() == countRequired)
    .FirstOrDefault()
    .OrEmptyIfNull()
    .ToList();
于 2019-03-14T00:49:12.817 回答