如何在嵌套引用中检查null

寻找一些最佳实践指导。 假设我有一行代码如下:

Color color = someOrder.Customer.LastOrder.Product.Color; 

其中Customer,LastOrder,Product和Color在正常情况下可以为null 。 但是,如果路径中的任何一个对象为null,我希望color为null; 为了避免空引用exception,我需要检查每个对象的空条件,例如

 Color color = someOrder == null || someOrder.Customer == null || someOrder.Customer.LastOrder == null || someOrder.Customer.Product == null ? null : someOrder.Customer.LastOrder.Product.Color; 

或者我可以做到这一点

 Color color = null; try {color = someOrder.Customer.LastOrder.Product.Color} catch (NullReferenceException) {} 

第一种方法显然有效,但编码和更难阅读似乎更乏味。 第二种方法稍微容易一些,但对此使用exception处理可能不是一个好主意。

是否有其他快捷方式检查空值并在必要时将null指定为颜色? 或者在使用这种嵌套引用时如何避免NullReferenceExceptions的任何想法?

您正在寻找null-safe解除引用运算符。

 Color color = someOrder?.Customer?.LastOrder?.Product?.Color; 

不幸的是C#不支持它。 也许它会在稍后添加,但目前还没有计划这样做。

有关

  • 深度检查,是否有更好的方法?

最佳做法是遵循得墨忒耳法则 ,听起来像:不要与陌生人交谈。 即对象应该避免调用另一个方法返回的成员对象的方法。 这允许编写较少耦合,更易于维护和可读的代码。

所以,避免像someOrder.Customer.LastOrder.Product.Color那样使用’train wrecks’,因为它们完全违反了Demeter法。 甚至很难理解这段代码的商业含义。 为什么你得到其他订单的产品颜色,这不是现在的订单?

消除火车残骸的可能方法 – 推动function更接近有趣的残骸结束。 在您的情况下,还要考虑将最后一个产品传递给您的方法,而不是使用某些订单。

你需要在哪里做到这一点。

用法

 Color color = someOrder.ComplexGet(x => x.Customer.LastOrder.Product.Color); 

要么

 Color color = Complex.Get(() => someOrder.Customer.LastOrder.Product.Color); 

帮助程序类实现

 public static class Complex { public static T1 ComplexGet(this T2 root, Func func) { return Get(() => func(root)); } public static T Get(Func func) { try { return func(); } catch (Exception) { return default(T); } } } 

我肯定更喜欢第一种方法……第二种方法利用程序流程的exception机制,这是不好的做法恕我直言…

AFAIK在C#中没有快捷方式或“空安全解除引用运算符”。

定义访问嵌套属性的唯一方法。 比如这样

 private Customoer GetCustomer(Order order) { return order != null ? order.Customer : null; } private Order GetLastOrder(Customer customer) { return customer != null ? customer.LastOrder : null; } 

使用定义的方法访问应用程序中的属性