我有以下类结构,我需要找到UpdatedDate
的最新Order
,即Order / Orderline / OrderlineSize / OrderlineVAS
的最大值。列表永远不会为空,但可能为空。
class Order
{
public List<Orderline> Orderlines { get; set; }
public DateTime UpdatedDate { get; set; }
}
class Orderline
{
public List<OrderlineSize> OrderLineSizes { get; set; }
public List<OrderlineVAS> OrderLineValueAddedServices { get; set; }
public DateTime UpdatedDate { get; set; }
}
class OrderlineSize
{
public DateTime UpdatedDate { get; set; }
}
class OrderlineVAS
{
public DateTime UpdatedDate { get; set; }
}
我正在使用以下代码获取Max
,如果有OrderLineSizes
这样可以正常工作,但当列表为空时会抛出NullReferenceException
。
(new List<DateTime?>() {
order.UpdatedDate,
order.Orderlines.Max(x=>x.UpdatedDate),
order.Orderlines.SelectMany(x=>x.OrderLineSizes).DefaultIfEmpty()?.Max(y=>y.UpdatedDate),
order.Orderlines.SelectMany(x=>x.OrderLineValueAddedServices).DefaultIfEmpty()?.Max(y=>y.UpdatedDate)
})
.Max().Value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
我使用C#6中的elvis操作解决了它,如下所示
(new List<DateTime?>() {
order.UpdatedDate,
order.Orderlines.Max(x=>x?.UpdatedDate),
order.Orderlines.SelectMany(x=>x.OrderLineSizes).Max(y=>y?.UpdatedDate),
order.Orderlines.SelectMany(x=>x.OrderLineValueAddedServices).Max(y=>y?.UpdatedDate)
})
.Max().Value.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ")
使用早期版本的C#
怎么解决?我认为在Linq中使用Select
子句但不确定这是否是一个不错的选择。
如何优化它以获得更好的性能?
答案 0 :(得分:1)
抛出异常:
.DefaultIfEmpty()?.Max(y=>y.UpdatedDate)
DefaultIfEmpty不返回null。相反,它返回一个带有单个null条目的枚举。因此它通过?。到马克斯。最后,在y.UpdateDate处理null,y == null,导致NullReferenceException。
通过删除?解决?从DefaultIfEmpty之后,而是在y之后添加它,如下所示:
.DefaultIfEmpty().Max(y=>y?.UpdatedDate)
这需要在这个模式出现的两行中完成。
此外,整个事情可以更加高效和简洁:
string result =
Enumerable.Repeat(order.UpdatedDate, 1)
.Concat(order.Orderlines.Select(x1 => x1.UpdatedDate))
.Concat(order.Orderlines.SelectMany(x => x.OrderLineSizes).Select(x => x.UpdatedDate))
.Concat(order.Orderlines.SelectMany(x => x.OrderLineValueAddedServices).Select(x => x.UpdatedDate))
.Max().ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");