Fluent null checking

When you want to access nested properties on an object, e.g. Person.Address.Postcode, it’s annoying and bloated having to write this as a series of variable assignments and null checks at each stage if the properties are nullable. The set of extensions below allows the following example:

public string GetSomething(A myClass) {
    var property1 = myClass.Property1;

    if (property1 == null) {
        return string.Empty;
    }

    var property2 = property1.Property2;

    if (property2 == null) {
        return string.Empty;
    }

    return property2.Property3 ?? string.Empty;
}

to be cleanly re-written as…

public string GetSomething(A myClass) {
    return myClass.With(x => x.Property1).With(x => x.Property2).Return(x => x.Property3, string.Empty);
}

using these extensions:

using System;

namespace Extensions
{
    public static class MaybeMonadExtensions
    {
        public static TResult With<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
            where TResult : class
            where TInput : class
        {
            return o == null ? null : evaluator(o);
        }

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

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

            return evaluator(o) ? o : null;
        }

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

            return evaluator(o) ? null : o;
        }

        public static TInput Do<TInput>(this TInput o, Action<TInput> action)
            where TInput : class
        {
            if (o == null)
            {
                return null;
            }

            action(o);
            return o;
        }
    }
}

See http://www.codeproject.com/KB/cs/maybemonads.aspx for more details.

Something to add?

This site uses Akismet to reduce spam. Learn how your comment data is processed.