Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Use .net 4.0's <code>ConcurrentDictionary&lt;A, R&gt;</code> without the unnecessary <code>Lazy&lt;R&gt;</code>.<br> The key is <code>GetOrAdd(A, Func&lt;A, R&gt;)</code> which renders into a beautifully trivial lambda.</p> <pre><code>public static Func&lt;A, R&gt; Memoize&lt;A, R&gt;(this Func&lt;A, R&gt; f) { var cache = new ConcurrentDictionary&lt;A, R&gt;(); return a =&gt; cache.GetOrAdd(a, f); }; </code></pre> <p><strong>Update</strong> The above solution does allow multiple simultaneous readers &amp; writers with the minimum of overhead. But, it doesn't prevent <code>f(a)</code> from being executed more than once for the same value (during the period while it is being calculated).</p> <p>If that is vital to you, you could wrap the value in <code>Lazy&lt;R&gt;</code> but you incur a cost for every read.</p> <pre><code>public static Func&lt;A, R&gt; Memoize&lt;A, R&gt;(this Func&lt;A, R&gt; f) { var cache = new ConcurrentDictionary&lt;A, Lazy&lt;R&gt;&gt;(); return a =&gt; cache.GetOrAdd(a, new Lazy&lt;R&gt;(() =&gt; f(a))).Value; } </code></pre> <p><strong>Update</strong> Timing tests for a million reads of a pre-populated 1000-item cache show <strong>19ms</strong> for <code>ConcurrentDictionary</code> -- same as regular <code>Dictionary</code> -- but <strong>720ms</strong> for the <code>Lazy</code> version.</p> <p>If that sounds too steep, you can get the best of both worlds with a more complex solution.</p> <pre><code>public static Func&lt;A, R&gt; Memoize&lt;A, R&gt;(this Func&lt;A, R&gt; f) { var cache = new ConcurrentDictionary&lt;A, R&gt;(); var syncMap = new ConcurrentDictionary&lt;A, object&gt;(); return a =&gt; { R r; if (!cache.TryGetValue(a, out r)) { var sync = syncMap.GetOrAdd(a, new object()); lock (sync) { r = cache.GetOrAdd(a, f); } syncMap.TryRemove(a, out sync); } return r; }; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload