通过Linq检查内部对象是否为null

时间:2019-02-18 09:29:53

标签: c# linq

我有一个list,记录很少,list里面还有另一个object。基于内部对象,我正在使用OrderByDescending。内部对象在少数地方是null,因此会抛出NullReferenceException

items.OrderByDescending(i=> i.Obj_Announcement.CreatedDate).ToList()

Obj_Announcementnull时,查询将引发异常。

不重复:我在OrderByDescending中有对象,而不是单个字段。

我该如何解决这个问题?

3 个答案:

答案 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)

根据期望的结果集,您基本上有两个选择。

  1. 排除实例,该实例为Obj_Announcement-属性为null。但是恕我直言,这不是问题的范围,它会改变程序的外观。

  2. 明确决定如何处理空值。

查看OrderByDescendinghttps://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.MinValueDateTime.MaxValue只是作为默认值的假设。它们不能反映对象的实际状态。

答案 2 :(得分:1)

items.OrderByDescending(i=> i.Obj_Announcement?.CreatedDate ?? DateTime.MinValue).ToList()

应该起作用,好像值是null一样,它将返回DateTime.MinValue(意味着null值将在后面),否则,您将只检索CreatedDate。

请注意,虽然我现在不在电脑前,所以无法测试。