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.
posted @ Thursday, August 05, 2010 9:57 PM