by Magnus Mårtensson - .Net, Tips & Tricks
Adding an implicit cast functionality to Lazy<T> can give you an option to writing null checkers in your delayed instantiation properties.
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:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
<span style="color: blue">private </span><span style="color: #2b91af">Foo </span>oldFooProp; <span style="color: blue">public </span><span style="color: #2b91af">Foo </span>OldFooProp { <span style="color: blue">get </span>{ <span style="color: blue">if </span>(oldFooProp == <span style="color: blue">null</span>) { oldFooProp = <span style="color: blue">new </span><span style="color: #2b91af">Foo</span>(); } <span style="color: blue">return </span>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:
|
1 2 3 4 5 6 7 |
<span style="color: blue">public </span><span style="color: #2b91af">Foo </span>OldAlternativeFooProp { <span style="color: blue">get </span>{ <span style="color: blue">return </span>oldFooProp ?? (oldFooProp = <span style="color: blue">new </span><span style="color: #2b91af">Foo</span>()); } } |
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:
|
1 2 3 4 5 6 7 8 9 |
<span style="color: blue">private </span><span style="color: #2b91af">Lazy</span><<span style="color: #2b91af">Foo</span>> foo = <span style="color: blue">new </span><span style="color: #2b91af">Lazy</span><<span style="color: #2b91af">Foo</span>>(); <span style="color: blue">public </span><span style="color: #2b91af">Foo </span>Foo { <span style="color: blue">get </span>{ <span style="color: blue">return </span>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 secret trick is to inherit Lazy<T> and implement an implicit operator for T on it!
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<span style="color: blue">namespace </span>Jayway.com.Sys { <span style="color: gray">/// <summary> /// </span><span style="color: green">A version of </span><span style="color: gray"><see cref="Sys.Lazy{T}"/> </span><span style="color: green">with the twist of being implicitly castable to </span><span style="color: gray"><typeparamref name="T"/></span><span style="color: green">. </span><span style="color: gray">/// </summary> /// <typeparam name="T"></span><span style="color: green">The type of lazy instance we are creating.</span><span style="color: gray"></typeparam> </span><span style="color: blue">public class </span><span style="color: #2b91af">Lazy</span><T> : System.<span style="color: #2b91af">Lazy</span><T> { <span style="color: blue"><pre class="code"><span style="color: green"><font color="#000000"> </font>// Ctors removed for brevity </span></span><span style="color: blue"><font color="#008000"></font> </span><span style="color: gray">/// <summary> /// </span><span style="color: green">Cast the </span><span style="color: gray"><see cref="Lazy{T}"/> </span><span style="color: green">to it's contained </span><span style="color: gray"><typeparamref name="T"/> /// </summary> /// <param name="lazyT"></span><span style="color: green">The lazy to cast.</span><span style="color: gray"></param> /// <returns></span><span style="color: green">The instance of </span><span style="color: gray"><see cref="Lazy{T}.Value"/></returns> </span><span style="color: blue">public static implicit operator </span>T(<span style="color: #2b91af">Lazy</span><T> lazyT) { <span style="color: blue">return </span>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:
|
1 2 3 4 5 6 7 8 9 |
<span style="color: blue">public </span>LazyTests() { <span style="color: green">// With parameter </span>theFoo = <span style="color: blue">new </span><span style="color: #2b91af">Lazy</span><<span style="color: #2b91af">Foo</span>>(() => <span style="color: blue">new </span><span style="color: #2b91af">Foo</span>(<span style="color: #a31515">"bar"</span>)); <span style="color: green">// With <a href="http://martinfowler.com/articles/injection.html">Inversion Of Control</a> </span><span style="color: #2b91af">IServiceLocator </span>serviceLocator = GetServiceLocator(); theFoo = <span style="color: blue">new </span><span style="color: #2b91af">Lazy</span><<span style="color: #2b91af">Foo</span>>(() => 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.
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.