Lazy<T> with implicit cast to T can give you some pretty code

Adding an implicit cast functionality to Lazy<T> can give you an option to writing null checkers in your delayed instantiation properties.

The problem

Today in our project a colleague was cussing over the fact that he kept writing the same block of code over and over again when null checking a property with a backing field.

Given the class Foo:

private Foo oldFooProp;
public Foo OldFooProp
{
    get
    {
        if (oldFooProp == null)
        {
            oldFooProp = new Foo();
        }
        return oldFooProp;
    }
}

Have any of you written something like this before? It’s a bunch of lines of code that you tend to write (in small variations) over and over again. Sure you can compact it a little but it in the order of 5 – 10 lines of annoying repetitive code.

Some use the null coalescing operator (??) version that looks like this:

public Foo OldAlternativeFooProp
{
    get
    {
        return oldFooProp ?? (oldFooProp = new Foo());
    }
}

This version is a little easier to compact down to even a single line.

But we (my colleague and I) can do you one better:

Here is an optional approach

private Lazy<Foo> foo = new Lazy<Foo>();

public Foo Foo
{
    get
    {
        return foo;
    }
}

Actually I’d prefer to do that like this but then you have to know the solution below and be comfortable with it:

public readonly Lazy<Foo> Foo = new Lazy<Foo>();

But wait a minute: That doesn’t work you say, right? You can’t return a Lazy<Foo> as a Foo you have to write theFoo.Value.

The Trick

The secret trick is to inherit Lazy<T> and implement an implicit operator for T on it!

namespace Jayway.com.Sys
{
    /// <summary>
    /// A version of <see cref="Sys.Lazy{T}"/> with the twist of being implicitly castable to <typeparamref name="T"/>.
    /// </summary>
    /// <typeparam name="T">The type of lazy instance we are creating.</typeparam>
    public class Lazy<T> : System.Lazy<T>
    {
        // Ctors removed for brevity

        /// <summary>
        /// Cast the <see cref="Lazy{T}"/> to it's contained <typeparamref name="T"/>
        /// </summary>
        /// <param name="lazyT">The lazy to cast.</param>
        /// <returns>The instance of <see cref="Lazy{T}.Value"/></returns>
        public static implicit operator T(Lazy<T> lazyT)
        {
            return lazyT.Value;
        }
    }
}

Now you can implicitly cast a Lazy<T> to it’s contained type T.

A few alternative constructions for it might look like this:

public LazyTests()
{
    // With parameter
    theFoo = new Lazy<Foo>(() => new Foo("bar"));

    // With Inversion Of Control
    IServiceLocator serviceLocator = GetServiceLocator();
    theFoo = new Lazy<Foo>(() => serviceLocator.GetInstance());
}

I kind of like this code. It’s compact. It’s easy to read. It’s pretty!

Hope you like it too – HTH!

Cheers,

M.

This Post Has One Comment

  1. Very nice! It this C# 4?

    I also noticed that you shouldn’t use it if your constructor function can throw an exception.

    > In general, implicit conversion operators should never throw exceptions and never lose information so that they can be used safely without the programmer’s awareness. If a conversion operator cannot meet those criteria, it should be marked explicit.

Leave a Reply

Close Menu