Nullsafe dereference operator (?.) as exists in some languages is a handy and nice pattern which saves a few bugs. Null references are serious problems and as people say nearly 70% of all bugs in the industry are directly or indirectly related to “Object reference not set to an instance of an object!”
However, there is noway to completely avoid null references, unless you write in a fully functional programming language like HASCUL. Some object oriented languages like groovy support a notion of nullsafe dereference operator which helps your null checks to be simpler. Here is the syntax in groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name
The above code returns the Name of the boss of the manager of the supervisor of an specific employee. It checks if any part of the right operand is null. If employee has no supervisor or supervisor has no manager, etc. bossName will become “null”.
Writing the above code in C# becomes like this:
bossName = Employee != null && Employee.Supervisor != null && Employee.Supervisor.Manager != null && Employee.Supervisor.Manager.Boss != null ? Employee.Supervisor.Manager.Boss.Name : null;
Pretty ugly, isn’t it? We can make a bunch of C# functions that takes us as closer to the groovy syntax of groovy. Note that nullsafe operator is going to be used in many places and inside the loops and it is not efficient to define any class for just a null check. Anyway a simple function won’t add much overhead.
//Groovy: bossName = Employee?.Supervisor?.Manager?.Boss?.Name //C#: bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager, m => m.Boss, b => b.Name);
This one looks much more beautiful and more readable and this the the Nullify (static) class:
public static class Nullify { public static TR Get<TF, TR>(TF t, Func<TF, TR> f) where TF : class { return t != null ? f(t) : default(TR); } 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 as for the pseudocode /// var r = Pharmacy?.GuildMembership?.State?.Name /// can be written as /// var r = Nullify( Pharmacy, p => p.GuildMembership, g => g.State, s => s.Name ); /// </summary> public static TR Get<T2, 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); } }
UPDATE:
Below is the alternative way by using extension methods. It is really your preference to decide which way is better. Above approach might have slightly less overhead since it just adds a single function call in the IL code and is more concise for short expressions, but the code is shorter in the bottom approach and visually looks better for larger expressions.
public static TOut NullSafe<TIn, TOut>(this TIn obj, Func<TIn, TOut> memberAction) { //Note we should not use obj != null because it can not test value types and also //compiler has to lift the type to a nullable type for doing the comparision with null. return (EqualityComparer<TIn>.Default.Equals(obj, default(TIn))) ? memberAction(obj) : default(TOut); } //Usage:.. Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss ).NullSafe( b => b.Name );