Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep null checking, is there a better way?

Tags:

c#

null

Note: This question was asked before the introduction of the .? operator in C# 6 / Visual Studio 2015.

We've all been there, we have some deep property like cake.frosting.berries.loader that we need to check if it's null so there's no exception. The way to do is is to use a short-circuiting if statement

if (cake != null && cake.frosting != null && cake.frosting.berries != null) ... 

This is not exactly elegant, and there should perhaps be an easier way to check the entire chain and see if it comes up against a null variable/property.

Is it possible using some extension method or would it be a language feature, or is it just a bad idea?

like image 412
Homde Avatar asked Jan 17 '10 10:01

Homde


People also ask

Why is checking for null a good practice?

It is a good idea to check for null explicitly because: You can catch the error earlier. You can provide a more descriptive error message.

How do you handle a null check in C#?

Empty(A constant for empty strings). This method will take a parameter that will be of System. String type. The method will return a Boolean value, like n case if the argument String type has null or empty string (“”), then it will return True value else it will return False value.


2 Answers

We have considered adding a new operation "?." to the language that has the semantics you want. (And it has been added now; see below.) That is, you'd say

cake?.frosting?.berries?.loader 

and the compiler would generate all the short-circuiting checks for you.

It didn't make the bar for C# 4. Perhaps for a hypothetical future version of the language.

Update (2014): The ?. operator is now planned for the next Roslyn compiler release. Note that there is still some debate over the exact syntactic and semantic analysis of the operator.

Update (July 2015): Visual Studio 2015 has been released and ships with a C# compiler that supports the null-conditional operators ?. and ?[].

like image 90
Eric Lippert Avatar answered Nov 08 '22 05:11

Eric Lippert


I got inspired by this question to try and find out how this kind of deep null checking can be done with an easier / prettier syntax using expression trees. While I do agree with the answers stating that it might be a bad design if you often need to access instances deep in the hierarchy, I also do think that in some cases, such as data presentation, it can be very useful.

So I created an extension method, that will allow you to write:

var berries = cake.IfNotNull(c => c.Frosting.Berries); 

This will return the Berries if no part of the expression is null. If null is encountered, null is returned. There are some caveats though, in the current version it will only work with simple member access, and it only works on .NET Framework 4, because it uses the MemberExpression.Update method, which is new in v4. This is the code for the IfNotNull extension method:

using System; using System.Collections.Generic; using System.Linq.Expressions;  namespace dr.IfNotNullOperator.PoC {     public static class ObjectExtensions     {         public static TResult IfNotNull<TArg,TResult>(this TArg arg, Expression<Func<TArg,TResult>> expression)         {             if (expression == null)                 throw new ArgumentNullException("expression");              if (ReferenceEquals(arg, null))                 return default(TResult);              var stack = new Stack<MemberExpression>();             var expr = expression.Body as MemberExpression;             while(expr != null)             {                 stack.Push(expr);                 expr = expr.Expression as MemberExpression;             }               if (stack.Count == 0 || !(stack.Peek().Expression is ParameterExpression))                 throw new ApplicationException(String.Format("The expression '{0}' contains unsupported constructs.",                                                              expression));              object a = arg;             while(stack.Count > 0)             {                 expr = stack.Pop();                 var p = expr.Expression as ParameterExpression;                 if (p == null)                 {                     p = Expression.Parameter(a.GetType(), "x");                     expr = expr.Update(p);                 }                 var lambda = Expression.Lambda(expr, p);                 Delegate t = lambda.Compile();                                 a = t.DynamicInvoke(a);                 if (ReferenceEquals(a, null))                     return default(TResult);             }              return (TResult)a;                     }     } } 

It works by examining the expression tree representing your expression, and evaluating the parts one after the other; each time checking that the result is not null.

I am sure this could be extended so that other expressions than MemberExpression is supported. Consider this as proof-of-concept code, and please keep in mind that there will be a performance penalty by using it (which will probably not matter in many cases, but don't use it in a tight loop :-) )

like image 41
driis Avatar answered Nov 08 '22 05:11

driis