我有一个list
,记录很少,list
里面还有另一个object
。基于内部对象,我正在使用OrderByDescending
。内部对象在少数地方是null
,因此会抛出NullReferenceException
。
items.OrderByDescending(i=> i.Obj_Announcement.CreatedDate).ToList()
当Obj_Announcement
为null
时,查询将引发异常。
不重复:我在OrderByDescending
中有对象,而不是单个字段。
我该如何解决这个问题?
答案 0 :(得分:3)
整洁的方法是将LINQ查询与定义哪个项目位于另一个项目之前的方式分开。换句话说:项目X和项目Y的排序顺序是什么
为此,我们需要创建一个实现IComparer<Item>
class Item
{
public Announcement Announcement {get; set;} // your inner object, might be null
...
}
class Announcement
{
public DateTime CreatedDate {get; set;}
...
}
假设您有两个Items
,其中一个为空Anouncement
。
Item item1 = new Item {Announcement = null};
Item item2 = new Item {Announcement = new AnnounceMent{CreatedDate=new DateTime(2000, 1, 1)}};
由您决定哪个先出现。假设您想在末尾输入空项目。
class ItemComparer : Comparer<Item>
{
public static readonly ByCreatedDate = new ItemComparer();
private static readonly IComparer<DateTime> dateComparer = Comparer<DateTime>.default;
public override int CompareTo(Item x, Item y)
{
// TODO: decide what to do if x or y null: exception? comes first? comes last
if (x.Announcement == null)
{
if (y.Announcement == null)
// x and y both have null announcement
return 0;
else
// x.Announcement null, y.Announcement not null: x comes last:
return +1;
}
else
{
if (y.Announcement == null)
// x.Announcement not null and y.Announcement null; x comes first
return -1;
else
// x.Announcement not null, y.Announcement not null: compare dates
return dateComparer.CompareTo(x.CreatedDate, y.CreateDate)
}
}
}
用法:
(在Peter Wurzinger评论后改进)
var result = items.OrderByDescending(item => item, ItemComparer.ByCreatedDate);
注意:如果决定更改Items的排序顺序,则要做的就是更改ItemComparer类。然后,所有用于订购商品的LINQ语句都将使用新的排序顺序。
答案 1 :(得分:2)
根据期望的结果集,您基本上有两个选择。
排除实例,该实例为Obj_Announcement
-属性为null。但是恕我直言,这不是问题的范围,它会改变程序的外观。
明确决定如何处理空值。
查看OrderByDescending
(https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderbydescending)的文档时,会遇到keySelector
参数。由于它是Func<TSource, TKey>
,因此应该能够处理TSource
实例可能显示的边缘情况-例如,在您的情况下,子对象上为null。
因此,恕我直言,最简单的解决方法是通过
items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MinValue).ToList()
或
items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MaxValue).ToList()
但是请注意,DateTime.MinValue
和DateTime.MaxValue
只是作为默认值的假设。它们不能反映对象的实际状态。
答案 2 :(得分:1)
items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MinValue).ToList()
应该起作用,好像值是null一样,它将返回DateTime.MinValue
(意味着null值将在后面),否则,您将只检索CreatedDate。
请注意,虽然我现在不在电脑前,所以无法测试。