An Implementation of Lazy(T) with Invalidation

I am a big fan of using Lazy<T> as my go-to implementation of the Singleton pattern. It works well and the thread safety is easily adjustable . While I won’t go into the details of how to use it, all the information is in the Lazy<T> documentation.

For what I needed, however, Lazy<T> fell a bit short. I essentially needed a cache of something that was expensive to create, and could be invalidated when the source object changed. In my case, I had a list that I needed to run some aggregate queries against. Running those queries is expensive, so I only want to re-run them when the list has changed, and I want to run them on demand (don’t compute until the last second when it is needed). In other words, I needed a really simple cache.

Thinking it to be easy enough to implement, I created one, using a Lazy<T> as the implementation. My class, the LazyCache<T>, behaves as you would expect Lazy<T> to behave, but with an additional method: Invalidate(). Please note that I didn’t test the thread safety of the LazyCache<T> and already see some potential problems, so if that is a requirement please take steps to ensure that it will behave as needed.

LazyCache<T> Usage

Here is some demo code that uses the LazyCache<T>

</p>
<p>[Test] public void LazyCache_DemonstrationWithObservableCollection()<br />
{<br />
var data = new ObservableCollection&lt;string&gt;() { "Hi", "Howru" };<br />
Func&lt;Dictionary&lt;string, int&gt;&gt; dataAsDic = () =&gt; data.ToDictionary(x =&gt; x, x =&gt; x.Length);<br />
var lazy = new LazyCache&lt;Dictionary&lt;string, int&gt;&gt;(dataAsDic);<br />
data.CollectionChanged += (sender, e) =&gt; lazy.Invalidate();</p>
<p>Assert.AreEqual(lazy.Value.Count, 2); // "Hi", "Howru"</p>
<p>data.Add("Tree");</p>
<p>Assert.AreEqual(lazy.Value.Count, 3); // "Hi", "Howru", "Tree"</p>
<p>data.RemoveAt(0); // "Howru", "Tree"<br />
data.RemoveAt(0); // "Tree"</p>
<p>Assert.AreEqual(lazy.Value.Count, 1); // "Tree"<br />
}</p>
<p>

LazyCache<T> Implementation

And here is my implementation of LazyCache<T>:

</p>
<p>public class LazyCache&lt;T&gt;<br />
{<br />
private readonly Func&lt;Lazy&lt;T&gt;&gt; lazyFactory;<br />
private Lazy&lt;T&gt; lazy;<br />
private Lazy&lt;T&gt; Lazy<br />
{<br />
get<br />
{<br />
if (lazy == null)<br />
{<br />
lazy = lazyFactory();<br />
}<br />
return lazy;<br />
}<br />
}</p>
<p>public LazyCache()<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;();<br />
}</p>
<p>public LazyCache(bool isThreadSafe)<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;(isThreadSafe);<br />
}</p>
<p>public LazyCache(Func&lt;T&gt; valueFactory)<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;(valueFactory);<br />
}</p>
<p>public LazyCache(LazyThreadSafetyMode mode)<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;(mode);<br />
}</p>
<p>public LazyCache(Func&lt;T&gt; valueFactory, bool isThreadSafe)<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;(valueFactory, isThreadSafe);<br />
}</p>
<p>public LazyCache(Func&lt;T&gt; valueFactory, LazyThreadSafetyMode mode)<br />
{<br />
lazyFactory = () =&gt; new Lazy&lt;T&gt;(valueFactory, mode);<br />
}</p>
<p>public bool IsValueCreated { get { return Lazy.IsValueCreated; } }<br />
public T Value { get { return Lazy.Value; } }<br />
public void Invalidate()<br />
{<br />
lazy = null;<br />
}<br />
}</p>
<p>

Leave a Reply

Your email address will not be published. Required fields are marked *