Nugs
Nugs

Reputation: 5793

Nullcheck multi level object

I'v been playing around with some shorter hand ways of checking multiple nested objects to see if any are null before proceeding. I'm trying to replace the multiple nested if statements into a single statement if possible using Null-conditional Operators.

So far i have something like this:

if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
{
...
}

Would the above be effective at identifying if either Object1 2 3 or 4 is null and return a false if so? I'm interested to hear if anyone has any better solutions?

TIA

Upvotes: 1

Views: 1573

Answers (3)

KeithS
KeithS

Reputation: 71591

What you have is currently the best way to do exactly what you want. I wanted to answer in order to illustrate what's necessary if you don't have access to the latest C# 6 language features. This is the next most developer-friendly way to make the same check in .NET 3.5-4.0:

    //boilerplate, off in your extension method library
    public static TOut OrDefault<TIn, TOut>(this TIn input, 
        Func<TIn, TOut> possiblyNullFunc)
    {
        try { return possiblyNullFunc(input); }
        catch (NullReferenceException) //for most reference types
        { return default(TOut); }
        catch (InvalidOperationException) //for Nullable<T>
        { return default(TOut); }
    }

    ...

    //usage
    if (Object1.OrDefault(o=>o.Object2.Object3.Object4) != null)
    {
        ...
    }

It functions pretty well, until you try to use InvalidOperationException in your own classes for situations other than null member access.

Still beats the pants off this, especially if you have to make this check a lot:

if(Object1 != null
    && Object1.Object2 != null
    && Object1.Object2.Object3 != null
    && Object1.Object2.Object3.Object4 != null)
{
    ...
}

Upvotes: 0

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236328

You don't need to return false or true - boolean condition itself has boolean value:

if (Object1?.Object2?.Object3?.Object4 != null)

This part is a completely valid option for checking nested objects if any of them is null. You can find exactly same example in null-conditional operator documentation:

// null if customers, the first customer, or Orders is null  
int? count = customers?[0]?.Orders?.Count();

And explanation:

The last example demonstrates that the null-condition operators are short-circuiting. If one operation in a chain of conditional member access and index operation returns null, then the rest of the chain’s execution stops.

Upvotes: 6

Scott Chamberlain
Scott Chamberlain

Reputation: 127603

The code

public void Foo()
{
    if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
    {
    ...
    }
}

is logically equivalent to

public void Foo()
{
    if ((NullCheck(Object1) != null) ? true : false)
    {
    ...
    }
}

private Object4Type NullCheck(Object1Type object1)
{
    if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
    {
        var tmpObject2 = tmpObject1.Object2;
        if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
        {
            var tmpObject3 = tmpObject2.Object3;
            if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
            {
                return tmpObject3.Object4;
            }        
        }
    }
    return default(Object4Type);
}

or if Object4Type is a struct

public void Foo()
{
    if ((NullCheck(Object1) != null) ? true : false)
    {
    ...
    }
}

private Nullable<Object4Type> NullCheck(Object1Type object1)
{
    if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
    {
        var tmpObject2 = tmpObject1.Object2;
        if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
        {
            var tmpObject3 = tmpObject2.Object3;
            if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
            {
                return tmpObject3.Object4;
            }        
        }
    }
    return default(Nullable<Object4Type>);
}

So your ... will only be run if all objects are not null and if a lower level object is null, the later objects never get evaluated.

Upvotes: 0

Related Questions