How to check for null in nested references

断了今生、忘了曾经 提交于 2019-12-19 02:26:07

问题


Looking for some best-practice guidance. Let's say I have a line of code like this:

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

where Customer, LastOrder, Product, and Color could be null under normal conditions. I'd like color to be null if any one of the objects in the path is null, however; in order to avoid null reference exceptions, I'd need to check for the null condition for each one of the objects, e.g.

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

or I could do this

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

The first method clearly works, but it seems a bit more tedious to code and harder to read. The second way is a bit easier but probably not a good idea to use exception handling for this.

Is there another shortcut way of checking for nulls and assigning null to color if necessary? Or any thoughts on how to avoid NullReferenceExceptions when using such nested references?


回答1:


You are looking for the null-safe dereferencing operator.

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

Unfortunately C# doesn't support it. Maybe it will be added later, but there are no plans to do that at the moment.

Related

  • Deep null checking, is there a better way?



回答2:


Best practice is to follow Law of Demeter which sounds as: don't talk to strangers. I.e. object should avoid invoking methods of a member object returned by another method. This allows to write less coupled, more maintainable and readable code.

So, avoid using 'train wrecks' like someOrder.Customer.LastOrder.Product.Color, because they completely violate Law of Demeter. It's even hard to understand what business meaning this code has. Why are you getting color of product of some other order, which is not the current one?

Possible way to remove train wreck - push functionality closer to interesting end of wreck. In your case, also consider passing last product to your method, instead of using some order.




回答3:


where you need to achieve this do this.

Usage

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

or

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

Helper Class Implementation

public static class Complex
{
    public static T1 ComplexGet<T1, T2>(this T2 root, Func<T2, T1> func)
    {
        return Get(() => func(root));
    }

    public static T Get<T>(Func<T> func)
    {
        try
        {
            return func();
        }
        catch (Exception)
        {
            return default(T);
        }
    }
}



回答4:


I would definitely prefer the first method... the second one exploits the exception mechanism for program flow which is bad practice IMHO...

AFAIK there is no shortcut or "null-safe dereferencing operator" in C# .




回答5:


Define unique method for accessing nested properties. For example like this

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

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

Using the defined method access your properties across the application



来源:https://stackoverflow.com/questions/10361868/how-to-check-for-null-in-nested-references

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!