C# elegant way to check if a property's property is null

C#NullreferenceexceptionNullableNull Conditional-Operator

C# Problem Overview


In C#, say that you want to pull a value off of PropertyC in this example and ObjectA, PropertyA and PropertyB can all be null.

ObjectA.PropertyA.PropertyB.PropertyC

How can I get PropertyC safely with the least amount of code?

Right now I would check:

if(ObjectA != null && ObjectA.PropertyA !=null && ObjectA.PropertyA.PropertyB != null)
{
    // safely pull off the value
    int value = objectA.PropertyA.PropertyB.PropertyC;
}

It would be nice to do something more like this (pseudo-code).

int value = ObjectA.PropertyA.PropertyB ? ObjectA.PropertyA.PropertyB : defaultVal;

Possibly even further collapsed with a null-coalescing operator.

EDIT Originally I said my second example was like js, but I changed it to psuedo-code since it was correctly pointed out that it would not work in js.

C# Solutions


Solution 1 - C#

In C# 6 you can use the Null Conditional Operator. So the original test will be:

int? value = objectA?.PropertyA?.PropertyB?.PropertyC;

Solution 2 - C#

Short Extension Method:

public static TResult IfNotNull<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
  where TResult : class where TInput : class
{
  if (o == null) return null;
  return evaluator(o);
}

Using

PropertyC value = ObjectA.IfNotNull(x => x.PropertyA).IfNotNull(x => x.PropertyB).IfNotNull(x => x.PropertyC);

This simple extension method and much more you can find on http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/

EDIT:

After using it for moment I think the proper name for this method should be IfNotNull() instead of original With().

Solution 3 - C#

Can you add a method to your class? If not, have you thought about using extension methods? You could create an extension method for your object type called GetPropC().

Example:

public static class MyExtensions
{
	public static int GetPropC(this MyObjectType obj, int defaltValue)
	{
		if (obj != null && obj.PropertyA != null & obj.PropertyA.PropertyB != null)
			return obj.PropertyA.PropertyB.PropertyC;
		return defaltValue;
	}
}

Usage:

int val = ObjectA.GetPropC(0); // will return PropC value, or 0 (defaltValue)

By the way, this assumes you are using .NET 3 or higher.

Solution 4 - C#

The way you're doing it is correct.

You could use a trick like the one described here, using Linq expressions :

int value = ObjectA.NullSafeEval(x => x.PropertyA.PropertyB.PropertyC, 0);

But it's much slower that manually checking each property...

Solution 5 - C#

Refactor to observe the Law of Demeter

Solution 6 - C#

Solution 7 - C#

You're obviously looking for the Nullable Monad:

string result = new A().PropertyB.PropertyC.Value;

becomes

string result = from a in new A()
                from b in a.PropertyB
                from c in b.PropertyC
                select c.Value;

This returns null, if any of the nullable properties are null; otherwise, the value of Value.

class A { public B PropertyB { get; set; } }
class B { public C PropertyC { get; set; } }
class C { public string Value { get; set; } }

LINQ extension methods:

public static class NullableExtensions
{
    public static TResult SelectMany<TOuter, TInner, TResult>(
        this TOuter source,
        Func<TOuter, TInner> innerSelector,
        Func<TOuter, TInner, TResult> resultSelector)
        where TOuter : class
        where TInner : class
        where TResult : class
    {
        if (source == null) return null;
        TInner inner = innerSelector(source);
        if (inner == null) return null;
        return resultSelector(source, inner);
    }
}

Solution 8 - C#

Assuming you have empty values of types one approach would be this:

var x = (((objectA ?? A.Empty).PropertyOfB ?? B.Empty).PropertyOfC ?? C.Empty).PropertyOfString;

I'm a big fan of C# but a very nice thing in new Java (1.7?) is the .? operator:

 var x = objectA.?PropertyOfB.?PropertyOfC.?PropertyOfString;

Solution 9 - C#

This code is "the least amount of code", but not the best practice:

try
{
    return ObjectA.PropertyA.PropertyB.PropertyC;
}
catch(NullReferenceException)
{
     return null;
}

Solution 10 - C#

When I need to chain calls like that, I rely on a helper method I created, TryGet():

	public static U TryGet<T, U>(this T obj, Func<T, U> func)
	{
		return obj.TryGet(func, default(U));
	}

	public static U TryGet<T, U>(this T obj, Func<T, U> func, U whenNull)
	{
		return obj == null ? whenNull : func(obj);
	}

In your case, you would use it like so:

	int value = ObjectA
		.TryGet(p => p.PropertyA)
		.TryGet(p => p.PropertyB)
		.TryGet(p => p.PropertyC, defaultVal);

Solution 11 - C#

I saw something in the new C# 6.0, this is by using '?' instead of checking

for example instead of using

if (Person != null && Person.Contact!=null && Person.Contact.Address!= null && Person.Contact.Address.City != null)
{ 
  var city = person.contact.address.city;
}

you simply use

var city = person?.contact?.address?.city;

I hope it helped somebody.


UPDATE:

You could do like this now

 var city = (Person != null)? 
           ((Person.Contact!=null)? 
              ((Person.Contact.Address!= null)?
                      ((Person.Contact.Address.City!=null)? 
                                 Person.Contact.Address.City : null )
                       :null)
               :null)
            : null;

Solution 12 - C#

You could do this:

class ObjectAType
{
    public int PropertyC
    {
        get
        {
            if (PropertyA == null)
                return 0;
            if (PropertyA.PropertyB == null)
                return 0;
            return PropertyA.PropertyB.PropertyC;
        }
    }
}



if (ObjectA != null)
{
    int value = ObjectA.PropertyC;
    ...
}

Or even better might be this:

private static int GetPropertyC(ObjectAType objectA)
{
    if (objectA == null)
        return 0;
    if (objectA.PropertyA == null)
        return 0;
    if (objectA.PropertyA.PropertyB == null)
        return 0;
    return objectA.PropertyA.PropertyB.PropertyC;
}


int value = GetPropertyC(ObjectA);

Solution 13 - C#

I would write your own method in the type of PropertyA (or an extension method if it's not your type) using the similar pattern to the Nullable type.

class PropertyAType
{
   public PropertyBType PropertyB {get; set; }
   
   public PropertyBType GetPropertyBOrDefault()
   {
       return PropertyB != null ? PropertyB : defaultValue;
   }
}

Solution 14 - C#

you can use the following extension and I think it is really good:

/// <summary>
/// Simplifies null checking
/// </summary>
public static TR Get<TF, TR>(TF t, Func<TF, TR> f)
	where TF : class
{
	return t != null ? f(t) : default(TR);
}

/// <summary>
/// Simplifies null checking
/// </summary>
public static TR Get<T1, T2, TR>(T1 p1, Func<T1, T2> p2, Func<T2, TR> p3)
	where T1 : class
	where T2 : class
{
	return Get(Get(p1, p2), p3);
}

/// <summary>
/// Simplifies null checking
/// </summary>
public static TR Get<T1, T2, T3, TR>(T1 p1, Func<T1, T2> p2, Func<T2, T3> p3, Func<T3, TR> p4)
	where T1 : class
	where T2 : class
	where T3 : class
{
	return Get(Get(Get(p1, p2), p3), p4);
}

And it is used like this:

int value = Nulify.Get(objectA, x=>x.PropertyA, x=>x.PropertyB, x=>x.PropertyC);

Solution 15 - C#

It is not possible.
ObjectA.PropertyA.PropertyB will fail if ObjectA is null due to null dereferencing, which is an error.

if(ObjectA != null && ObjectA.PropertyA ... works due to short circuiting, ie ObjectA.PropertyA will never be checked if ObjectA is null.

The first way you propose is the best and most clear with intent. If anything you could try to redesign without having to rely on so many nulls.

Solution 16 - C#

This approach is fairly straight-forward once you get over the lambda gobbly-gook:

public static TProperty GetPropertyOrDefault<TObject, TProperty>(this TObject model, Func<TObject, TProperty> valueFunc)  
                                                        where TObject : class
    {
        try
        {
            return valueFunc.Invoke(model);
        }
        catch (NullReferenceException nex)
        {
            return default(TProperty);
        }
    }

With usage that might look like:

ObjectA objectA = null;

Assert.AreEqual(0,objectA.GetPropertyOrDefault(prop=>prop.ObjectB.ObjectB.ObjectC.ID));

Assert.IsNull(objectA.GetPropertyOrDefault(prop => prop.ObjectB));

Solution 17 - C#

Just stumbled accross this post.

Some time ago I made a suggestion on Visual Studio Connect about adding a new ??? operator.

http://visualstudio.uservoice.com/forums/121579-visual-studio/suggestions/4104392-add-as-an-recursive-null-reference-check-opera

This would require some work from the framework team but don't need to alter the language but just do some compiler magic. The idea was that the compiler should change this code (syntax not allowed atm)

string product_name = Order.OrderDetails[0].Product.Name ??? "no product defined";

into this code

Func<string> _get_default = () => "no product defined"; 
string product_name = Order == null 
    ? _get_default.Invoke() 
    : Order.OrderDetails[0] == null 
        ? _get_default.Invoke() 
        : Order.OrderDetails[0].Product == null 
            ? _get_default.Invoke() 
            : Order.OrderDetails[0].Product.Name ?? _get_default.Invoke()

For null check this could look like

bool isNull = (Order.OrderDetails[0].Product ??? null) == null;

Solution 18 - C#

I wrote a method that accepts a default value, here is how to use it:

var teacher = new Teacher();
return teacher.GetProperty(t => t.Name);
return teacher.GetProperty(t => t.Name, "Default name");

Here is the code:

public static class Helper
{
    /// <summary>
    /// Gets a property if the object is not null.
    /// var teacher = new Teacher();
    /// return teacher.GetProperty(t => t.Name);
    /// return teacher.GetProperty(t => t.Name, "Default name");
    /// </summary>
    public static TSecond GetProperty<TFirst, TSecond>(this TFirst item1,
        Func<TFirst, TSecond> getItem2, TSecond defaultValue = default(TSecond))
    {
        if (item1 == null)
        {
            return defaultValue;
        }

        return getItem2(item1);
    }
}

Solution 19 - C#

var result = nullableproperty ?? defaultvalue;

The ?? (null-coalescing operator) means if the first argument is null, return the second one instead.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJon KraghView Question on Stackoverflow
Solution 1 - C#Phillip NganView Answer on Stackoverflow
Solution 2 - C#Krzysztof MorcinekView Answer on Stackoverflow
Solution 3 - C#SamView Answer on Stackoverflow
Solution 4 - C#Thomas LevesqueView Answer on Stackoverflow
Solution 5 - C#rtalbotView Answer on Stackoverflow
Solution 6 - C#Colonel PanicView Answer on Stackoverflow
Solution 7 - C#dtbView Answer on Stackoverflow
Solution 8 - C#Just another metaprogrammerView Answer on Stackoverflow
Solution 9 - C#Boris ModylevskyView Answer on Stackoverflow
Solution 10 - C#EmanuelView Answer on Stackoverflow
Solution 11 - C#iYazee6View Answer on Stackoverflow
Solution 12 - C#Jeffrey L WhitledgeView Answer on Stackoverflow
Solution 13 - C#Steve DannerView Answer on Stackoverflow
Solution 14 - C#TonyView Answer on Stackoverflow
Solution 15 - C#DanDanView Answer on Stackoverflow
Solution 16 - C#BlackjacketMackView Answer on Stackoverflow
Solution 17 - C#Jürgen SteinblockView Answer on Stackoverflow
Solution 18 - C#Akira YamamotoView Answer on Stackoverflow
Solution 19 - C#Aridane ÁlamoView Answer on Stackoverflow