Skip to content

Instantly share code, notes, and snippets.

@michaeljbailey
Created July 14, 2015 14:43
Show Gist options
  • Save michaeljbailey/202523e9f887c855f980 to your computer and use it in GitHub Desktop.
Save michaeljbailey/202523e9f887c855f980 to your computer and use it in GitHub Desktop.
Just some simple memoization implementations. Probably done a million times but here it is because I'm too lazy to go searching each time.
using System;
using System.Collections.Generic;
public static class CacheFunctionExtensions
{
public static Func<TResult> Memoize<TResult>(this Func<TResult> function, bool threadSafe = false)
{
var lazy = new Lazy<TResult>(function, threadSafe);
return () => lazy.Value;
}
public static Func<T1, TResult> Memoize<T1, TResult>(this Func<T1, TResult> function)
{
return Memoize(function, new Dictionary<T1, TResult>());
}
public static Func<T1, TResult> Memoize<T1, TResult>(this Func<T1, TResult> function, IDictionary<T1, TResult> cache)
{
return arg1 => GetOrAdd(cache, arg1, function);
}
public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> function)
{
return Memoize(function, new Dictionary<Tuple<T1, T2>, TResult>());
}
public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> function, IDictionary<Tuple<T1, T2>, TResult> cache)
{
return (arg1, arg2) => GetOrAdd(cache, Tuple.Create(arg1, arg2), tuple => function(tuple.Item1, tuple.Item2));
}
public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> function)
{
return Memoize(function, new Dictionary<Tuple<T1, T2, T3>, TResult>());
}
public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> function, IDictionary<Tuple<T1, T2, T3>, TResult> cache)
{
return (arg1, arg2, arg3) => GetOrAdd(cache, Tuple.Create(arg1, arg2, arg3), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3));
}
public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> function)
{
return Memoize(function, new Dictionary<Tuple<T1, T2, T3, T4>, TResult>());
}
public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> function, IDictionary<Tuple<T1, T2, T3, T4>, TResult> cache)
{
return (arg1, arg2, arg3, arg4) => GetOrAdd(cache, Tuple.Create(arg1, arg2, arg3, arg4), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4));
}
private static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> cache, TKey key, Func<TKey, TValue> function)
{
TValue value;
if (!cache.TryGetValue(key, out value))
{
return cache[key] = function(key);
}
return value;
}
}
using System;
using System.Collections.Concurrent;
public static class ConcurrentCacheFunctionExtensions
{
public static Func<T1, TResult> Memoize<T1, TResult>(this Func<T1, TResult> function, ConcurrentDictionary<T1, TResult> cache)
{
return arg1 => cache.GetOrAdd(arg1, function);
}
public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> function, ConcurrentDictionary<Tuple<T1, T2>, TResult> cache)
{
return (arg1, arg2) => cache.GetOrAdd(Tuple.Create(arg1, arg2), tuple => function(tuple.Item1, tuple.Item2));
}
public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> function, ConcurrentDictionary<Tuple<T1, T2, T3>, TResult> cache)
{
return (arg1, arg2, arg3) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3));
}
public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> function, ConcurrentDictionary<Tuple<T1, T2, T3, T4>, TResult> cache)
{
return (arg1, arg2, arg3, arg4) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3, arg4), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4));
}
public static Func<T1, T2, T3, T4, T5, TResult> Memoize<T1, T2, T3, T4, T5, TResult>(this Func<T1, T2, T3, T4, T5, TResult> function, ConcurrentDictionary<Tuple<T1, T2, T3, T4, T5>, TResult> cache)
{
return (arg1, arg2, arg3, arg4, arg5) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3, arg4, arg5), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5));
}
}
using System;
using System.Runtime.Caching;
public static class ExpiringCacheFunctionExtensions
{
public static Func<TResult> Memoize<TResult>(this Func<TResult> function, ObjectCache cache, TimeSpan expiration)
{
return () => cache.GetOrAdd(function, _ => function(), expiration);
}
public static Func<T1, TResult> Memoize<T1, TResult>(this Func<T1, TResult> function, ObjectCache cache, TimeSpan expiration)
{
return arg1 => cache.GetOrAdd(arg1, function, expiration);
}
public static Func<T1, T2, TResult> Memoize<T1, T2, TResult>(this Func<T1, T2, TResult> function, ObjectCache cache, TimeSpan expiration)
{
return (arg1, arg2) => cache.GetOrAdd(Tuple.Create(arg1, arg2), tuple => function(tuple.Item1, tuple.Item2), expiration);
}
public static Func<T1, T2, T3, TResult> Memoize<T1, T2, T3, TResult>(this Func<T1, T2, T3, TResult> function, ObjectCache cache, TimeSpan expiration)
{
return (arg1, arg2, arg3) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3), expiration);
}
public static Func<T1, T2, T3, T4, TResult> Memoize<T1, T2, T3, T4, TResult>(this Func<T1, T2, T3, T4, TResult> function, ObjectCache cache, TimeSpan expiraton)
{
return (arg1, arg2, arg3, arg4) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3, arg4), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4), expiraton);
}
public static Func<T1, T2, T3, T4, T5, TResult> Memoize<T1, T2, T3, T4, T5, TResult>(this Func<T1, T2, T3, T4, T5, TResult> function, ObjectCache cache, TimeSpan expiraton)
{
return (arg1, arg2, arg3, arg4, arg5) => cache.GetOrAdd(Tuple.Create(arg1, arg2, arg3, arg4, arg5), tuple => function(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4, tuple.Item5), expiraton);
}
private static TValue GetOrAdd<TKey, TValue>(this ObjectCache cache, TKey key, Func<TKey, TValue> function, TimeSpan expiration)
{
var hashKey = key.GetHashCode().ToString();
var existing = cache.Get(hashKey);
if (existing != null)
{
return (TValue)Convert.ChangeType(existing, typeof(TValue));
}
var newValue = function(key);
cache.Add(hashKey, newValue, new CacheItemPolicy { SlidingExpiration = expiration });
return newValue;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment