How to check for nulls in a deep lambda expression?

c#, lambda, linq

Solution

You can't do that in a concise way. You can either make the lambda multiple lines, or use nested ternary operators:

var result = GetValue(one, x => x.Two == null ? null :
                                x.Two.Three == null ? null :
                                x.Two.Three.Four == null ? null :
                                x.Two.Three.Four.Foo;

Ugly, I know.

Problem

How can I check for nulls in a deep lamda expression? Say for example I have a class structure that was nested several layers deep, and I wanted to execute the following lambda: ``` x => x.Two.Three.Four.Foo ``` I want it to return null if Two, Three, or Four were null, rather than throwing a System.NullReferenceException. ``` public class Tests { // This test will succeed [Fact] public void ReturnsValueWhenClass2NotNull() { var one = new One(); one.Two = new Two(); one.Two.Three = new Three(); one.Two.Three.Four = new Four(); one.Two.Three.Four.Foo = "blah"; var result = GetValue(one, x => x.Two.Three.Four.Foo); Assert.Equal("blah", result); } // This test will fail [Fact] public void ReturnsNullWhenClass2IsNull() { var one = new One(); var result = GetValue(one, x => x.Two.Three.Four.Foo); Assert.Equal(null, result); } private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression) { var func = expression.Compile(); var value = func(model); return value; } public class One { public Two Two { get; set; } } public class Two { public Three Three { get; set; } } public class Three { public Four Four { get; set; } } public class Four { public string Foo { get; set; } public string Bar { get; set; } } } ``` UPDATE: One solution would be to catch the NullReferenceException like this: ``` private TResult GetValue<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression) { TResult value; try { var func = expression.Compile(); value = func(model); } catch (NullReferenceException) { value = default(TResult); } return value; } ``` But I hate to incur the expense of catching an exception that is not, in my mind, exceptional. I expect this to be the case quite often in my domain. UPDATE 2: Another solution would be modify the property getters like this: ``` public class One { private Two two; public Two Two { get { return two ?? new Two(); } set { two = value; } } } ``` Which is mostly ok for my domain, but there are times when I really to expect a property to return null. I checked the answer from Josh E as helpful since it comes pretty close to what I need in some cases.

Original source

Related problems