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.
Magnus Mårtensson
Consultant at Jayway

1 comment so far ↓
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 Comment