Created
July 14, 2015 14:43
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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