Let\'s take Wes Dyer\'s approach to function memoization as the starting point:
public static Func Memoize(this Func f)
{
Expanding on Nigel Touch's excellent answer, I wanted to offer a reusable component extracted from his solution limiting the invocation count for f(a).
I called it SynchronizedConcurrentDictionary, and it looks like this:
public class SynchronizedConcurrentDictionary : ConcurrentDictionary
{
private readonly ReaderWriterLockSlim _cacheLock = new ReaderWriterLockSlim();
public new TValue GetOrAdd(TKey key, Func valueFactory)
{
TValue result;
_cacheLock.EnterWriteLock();
try
{
result = base.GetOrAdd(key, valueFactory);
}
finally
{
_cacheLock.ExitWriteLock();
}
return result;
}
}
Then the Memoize function becomes a two-liner:
public static Func Memoize(this Func f)
{
var cache = new SynchronizedConcurrentDictionary();
return key => cache.GetOrAdd(key, f);
}
Cheers!