LINQ中的ThenBy可能为空。

4

我正在尝试对一个视图模型进行多属性排序绑定。问题是第二个属性可能为空,从而导致出现空引用异常。

return this.People
  .OrderBy(x => x.Car.Name)
  .ThenBy(x => x.Pet.Name);

如果Pet为null,我该如何按Pet.Name进行ThenBy排序?

1
您想如何排序空宠物,是先放在最前面还是最后面? - Tim Schmelter
4个回答

10

这应该返回 null 宠物在非null宠物之前。

return this.People
  .OrderBy(x => x.Car.Name)
  .ThenBy(x => x.Pet != null ? x.Pet.Name : "");

1
x.Pet != null ? x.Pet.Name : "" 替换为更简洁(且不易出错)的空值合并运算符如何? x.Pet ?? string.Empty - spender
2
@spender:只有当 Pet 实现了 IComparable 接口时,这个方法才会有效。 - Tim Schmelter
糟糕,我读错了答案。宠物不一定是字符串。 - spender

3
如果您希望没有宠物的人在排序时排在有宠物的人前面,可以使用以下代码:
return this.People
  .OrderBy(x => x.Car.Name)
  .ThenBy(x => x.Pet == null ? string.Empty : x.Pet.Name);

如果您需要进行许多涉及宠物的排序操作,可以创建一个自己的PetComparer类,该类继承自Comparer<Pet>,如下所示:

public class Pet
{
    public string Name { get; set; }
    // other properties
}

public class PetComparer : Comparer<Pet> // 
{
    public override int Compare(Pet x, Pet y)
    {
        if (x == null) return -1; // y is considered greater than x
        if (y == null) return 1; // x is considered greater than y
        return x.Name.CompareTo(y.Name);
    }
}

现在,您的查询应该是这样的:
return this.People
  .OrderBy(x => x.Car.Name)
  .ThenBy(x => x.Pet, new PetComparer());

注意:这将与此答案顶部的查询相反 - 它将把没有宠物的人排在底部(在汽车名称内)。

没问题...我添加了一些额外的内容。 - devuxer

2
您可以使用空对象模式来处理宠物和汽车等情况,避免在这些情况下进行任何额外的null检查,并最小化可能出现NullReferenceException 的风险。

很好的观点。我应该这样做。其他人直接回答了问题。谢谢! - Bob Horn

0
使用空值条件(?.)和空合并(??)运算符,您可以这样做 -
return this.People
  .OrderBy(x => x.Car.Name)
  .ThenBy(x => x.Pet?.Name ?? string.Empty);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接