Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check for null in nested references

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?

like image 559
Eren Ersönmez Avatar asked Apr 28 '12 08:04

Eren Ersönmez


People also ask

Is Java 8 null check?

Using … != null still is the way to do it in Java 8 and even Java 11. Otherwise, it's like using a smartphone to hammer a nail into the wall, “to show the 2018 way of doing it”.

How do I avoid multiple nulls in Java 8?

Java 8 introduced an Optional class which is a nicer way to avoid NullPointerExceptions. You can use Optional to encapsulate the potential null values and pass or return it safely without worrying about the exception. Without Optional, when a method signature has return type of certain object.


3 Answers

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?
like image 102
Mark Byers Avatar answered Oct 03 '22 16:10

Mark Byers


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.

like image 37
Sergey Berezovskiy Avatar answered Oct 03 '22 14:10

Sergey Berezovskiy


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);
        }
    }
}
like image 29
kernowcode Avatar answered Oct 03 '22 14:10

kernowcode