C# 检查orderby Linq中的对象null
我有一个C# 检查orderby Linq中的对象null,c#,linq,C#,Linq,我有一个列表几乎没有记录,列表中有另一个对象。基于内部对象,我使用的是OrderByDescending。内部对象在少数位置为null,因此它正在抛出NullReferenceException items.OrderByDescending(i=> i.Obj_Announcement.CreatedDate).ToList() 当Obj_Announcement为null时,查询抛出异常 不重复:我在OrderByDescending中有对象,而不是单个字段 我如何解决这个问题 it
列表
几乎没有记录,列表
中有另一个对象
。基于内部对象,我使用的是OrderByDescending
。内部对象在少数位置为null
,因此它正在抛出NullReferenceException
items.OrderByDescending(i=> i.Obj_Announcement.CreatedDate).ToList()
当Obj_Announcement
为null
时,查询抛出异常
不重复:我在OrderByDescending
中有对象,而不是单个字段
我如何解决这个问题
items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MinValue).ToList()
如果该值为null,则它将返回DateTime.MinValue
(意味着null值将在后面),否则,您将只检索CreatedDate
请注意,我现在不在电脑前,因此无法测试。根据预期的结果集,您基本上有两个选项
Obj_Announcement
-属性为空。但我认为这不是问题的范围,它会改变这个项目的前景OrderByDescending
()文档时,会遇到keySelector
参数。由于它是一个Func
函数,它应该能够处理TSource
实例可能显示的边缘情况,例如,在您的情况下,子对象上的空值。
因此,解决这个问题的最简单的方法是,通过
items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MinValue).ToList()
或
但是请注意,
DateTime.MinValue
和DateTime.MaxValue
只是作为默认值的假设。它们并不反映对象的实际状态。最简洁的方法是将LINQ查询与定义哪个项位于另一项之前的方式分开。换句话说,项目X和项目Y的排序顺序是什么
为此,我们需要创建一个实现IComparer
假设您有两个项
,其中一个有空的声明
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)
}
}
}
注意:如果您决定更改项目的排序顺序,您所要做的就是更改ItemComparer类。所有对项目进行排序的LINQ语句都将使用新的排序顺序。要解决此问题,您应首先决定
null
值应如何排序。它们应该是最低的还是最高的?@RenéVogt-我需要最新的记录在顶部,这样我就需要了。网络库不允许DateTime对象为空。通常我使用一个新的DateTime,它将默认日期设置为1/1/1。然后,我通过检查日期是否大于1/1/1来测试空值。您应该对内部对象的hasValue排序,然后根据其值对列表排序:items.OrderByDescending(I=>I.Obj_Announcement.CreatedDate.hasValue)。然后通过Descending(I=>I.Obj_Announcement.CreatedDate.value)
+1,这是一个很好的答案!但是我认为,OrderByDescending(IEnumerable,IComparer)
根据。Imho调用因此应该看起来像items.OrderByDescending(item=>item,ItemComparer.ByCreatedDate)
应该注意的是,当与IQueryable
like或mapping、OData或任何东西一起使用时,它很可能不可翻译。
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)
}
}
}
var result = items.OrderByDescending(item => item, ItemComparer.ByCreatedDate);