« Data binding in a FlowDocument or Text Block | Main | Introductions »

January 14, 2008

Null-propagating extension method

Brad Wilson recently discovered that C# extension methods work on null references. We also discovered this interesting feature while developing a null-propagating extension method that we call IfNotNull:

public static class IfNotNullExtensionMethod

{

    public static U IfNotNull<T, U>(this T t, Func<T, U> fn)

    {

        return t != null ? fn(t) : default(U);

    }

}

Since this is an extension method on T, where T has no constraints, it is always available to any class or struct instance, much like Equals and GetHashCode. Therefore, we put it in its own namespace so that it only appears when requested.

You'll notice that the IfNotNull method is only an obscure way to call the specified delegate on the instance, except that we check to see whether the instance is null, and don't call the delegate in that case, returning null (or the default value in the case of a struct).

How do we use this method? Well, suppose you have an item with a Parent property and you want to get the Name of its parent.

string parentName = item.Parent.Name;

But suppose that item might be null, or the item's parent might be null, and you'd like the name variable to be null in either case.

string parentName = null;

if (item != null)

{

    Item parent = item.Parent;

    if (parent != null)

        parentName = parent.Name;

}

Or, more concisely:

Item parent = item == null ? null : item.Parent;

string parentName = parent == null ? null : parent.Name;

It would be nice to eliminate the temporary 'parent' variable, but we'd have to call the Parent property twice:

string parentName = item == null ? null : item.Parent == null ? null : item.Parent.Name;

The IfNotNull extension method allows us to eliminate the temporary 'parent' variable without calling the Parent property twice:

string parentName = item.IfNotNull(x => x.Parent).IfNotNull(x => x.Name);

The use of lambda expressions makes using IfNotNull the least efficient of all of the possibilities, so only use it when you believe the increased code clarity outweighs the performance loss.

Some programmers may legitimately feel that it doesn't improve code clarity at all. This was the best we could come up with in lieu of the ?. operator proposed by Miral, which would allow this:

string parentName = item?.Parent?.Name;

Update: Renamed the extension method from "To" to "IfNotNull"; the new name makes the semantics of the method clearer. We still have a To extension method, but it's even simpler:

public static U To<T, U>(this T t, Func<T, U> fn)

{

    return fn(t);

}

What possible use could this method have? Eliminating temporary variables. Here's a simple example:

IList<int> list = BuildListOfNumbers();

int nFirstOrDefault = list.Count == 0 ? 0 : list[0];

becomes

int nFirstOrDefault =

    BuildListOfNumbers().To(list => list.Count == 0 ? 0 : list[0]);

For what it's worth.

Posted by Ed Ball at January 14, 2008 8:30 AM

Trackback Pings

TrackBack URL for this entry:
http://ancientblogs.logos.com/mt-cgi/mt-tb.cgi/173