如何在嵌套引用中检查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; }
使用定义的方法访问应用程序中的属性