65.9K
CodeProject is changing. Read more.
Home

Walk 'object tree' with easy null handling

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (2 votes)

Dec 6, 2010

CPOL
viewsIcon

13161

A simple 'NullHelper' class helps dealing with walking an object tree without the need for null checking at each step. The solution is efficient because it does not use reflection.

This is useful when: 1) You need to get a property-of-a-property-of-a-property-of-a-property 2) One of the objects in the path may be null, but you don't want to check each one individually Note 1: This solution is a bit raw, because any null reference exception will be ignored, even when it occurs at the end of the path. Note 2: Java has some nice support for this problem, see Programming mistake No. 1: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292[^]
using System;

namespace NullHelperTest
{
    /// <summary>
    /// Helps in dealing with null.
    /// </summary>
    public static class NullHelper
    {
        /// <summary>
        /// Delegate for getting the value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public delegate T GetDelegate<T>()
            where T : class;

        /// <summary>
        /// Executes delegate and returns null if null reference exception was thrown.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="getDelegate"></param>
        /// <returns></returns>
        public static T Get<T>(GetDelegate<T> getDelegate)
            where T : class
        {
            T result = null;
            try
            {
                // Execute delegate to retrieve value
                result = getDelegate();
            }
            catch (NullReferenceException)
            {
                // Ignore
            }
            return result;
        }
    }

    public class Level1
    {
        public Level2 Level2 = null;
    }
    public class Level2
    {
        public Level3 Level3 = null;
        public Level3 GetLevel3()
        {
            return this.Level3;
        }
    }
    public class Level3
    {
    }
    class Program
    {
        static void ClassicApproach(Level1 level1)
        {
            if (level1 != null)
            {
                Level2 level2 = level1.Level2;
                if (level2 != null)
                {
                    Level3 level3 = level2.Level3;
                    if (level3 != null)
                    {
                        // use level 3
                    }
                    else
                    {
                        Console.WriteLine("From classic: level 3 is null");
                    }
                }
                else
                {
                    Console.WriteLine("From classic: level 2 is null");
                }
            }
            else
            {
                Console.WriteLine("From classic: level 1 is null");
            }
        }
        static void NewApproach(Level1 level1)
        {
            Level3 level3 = NullHelper.Get<Level3>(() => level1.Level2.Level3);
            if (level3 != null)
            {
                // use level 3
            }
            else
            {
                Console.WriteLine("From new: level 3 is null");
            }
        }
        static void Main(string[] args)
        {
            Level1 level1 = new Level1();
            ClassicApproach(level1);
            NewApproach(level1);
        }
    }
}