/// <summary> /// Memoizer with two parameters, used to perform a lazy-cached evaluation. (see http://en.wikipedia.org/wiki/Memoization) /// </summary> /// <typeparam name="T">The return type to memoize</typeparam> /// <param name="func">the function to evaluate</param> /// <returns>A memoized value</returns> public static Func <TArg1, TArg2, TResult> AsLockedMemoized <TArg1, TArg2, TResult>(this Func <TArg1, TArg2, TResult> func) { #if XAMARIN // On Xamarin.iOS, the SynchronizedDictionary type costs a lot in terms of // generic delegates, where trampolines are used a lot. As simple lock will not create that // much contention for now. var values = new Dictionary <CachedTuple <TArg1, TArg2>, TResult>(CachedTuple <TArg1, TArg2> .Comparer); return((arg1, arg2) => { var tuple = CachedTuple.Create(arg1, arg2); lock (values) { return values.FindOrCreate( tuple, () => func(tuple.Item1, tuple.Item2) ); } }); #elif !HAS_NO_CONCURRENT_DICT var values = new ConcurrentDictionary <CachedTuple <TArg1, TArg2>, TResult>(CachedTuple <TArg1, TArg2> .Comparer); return((arg1, arg2) => { var tuple = CachedTuple.Create(arg1, arg2); return values.GetOrAdd( tuple, // Use the parameter to avoid closure heap allocation k => func(k.Item1, k.Item2) ); }); #else var values = new SynchronizedDictionary <Tuple <TArg1, TArg2>, TResult>(); return((arg1, arg2) => { TResult value = default(TResult); var tuple = Tuple.Create(arg1, arg2); values.Lock.Write( v => v.TryGetValue(tuple, out value), v => value = values[tuple] = func(arg1, arg2) ); return value; }); #endif }
/// <summary> /// Memoizer with four parameters, used to perform a lazy-cached evaluation. (see http://en.wikipedia.org/wiki/Memoization) /// </summary> /// <typeparam name="T">The return type to memoize</typeparam> /// <param name="func">the function to evaluate</param> /// <returns>A memoized value</returns> public static Func <TArg1, TArg2, TArg3, TArg4, TResult> AsLockedMemoized <TArg1, TArg2, TArg3, TArg4, TResult>(this Func <TArg1, TArg2, TArg3, TArg4, TResult> func) { #if XAMARIN var values = new Dictionary <CachedTuple <TArg1, TArg2, TArg3, TArg4>, TResult>(CachedTuple <TArg1, TArg2, TArg3, TArg4> .Comparer); return((arg1, arg2, arg3, arg4) => { var tuple = CachedTuple.Create(arg1, arg2, arg3, arg4); lock (values) { return values.FindOrCreate( tuple, // Use the parameter to avoid closure heap allocation () => func(tuple.Item1, tuple.Item2, tuple.Item3, tuple.Item4) ); } }); #elif !HAS_NO_CONCURRENT_DICT var values = new ConcurrentDictionary <CachedTuple <TArg1, TArg2, TArg3, TArg4>, TResult>(CachedTuple <TArg1, TArg2, TArg3, TArg4> .Comparer); return((arg1, arg2, arg3, arg4) => { var tuple = CachedTuple.Create(arg1, arg2, arg3, arg4); return values.GetOrAdd( tuple, // Use the parameter to avoid closure heap allocation k => func(k.Item1, k.Item2, k.Item3, k.Item4) ); }); #else var values = new SynchronizedDictionary <Tuple <TArg1, TArg2, TArg3, TArg4>, TResult>(); return((arg1, arg2, arg3, arg4) => { TResult value = default(TResult); var tuple = new Tuple <TArg1, TArg2, TArg3, TArg4>(arg1, arg2, arg3, arg4); values.Lock.Write( v => v.TryGetValue(tuple, out value), v => value = values[tuple] = func(arg1, arg2, arg3, arg4) ); return value; }); #endif }
/// <summary> /// Memoizer with two parameters, used to perform a lazy-cached evaluation. (see http://en.wikipedia.org/wiki/Memoization) /// </summary> /// <typeparam name="TParam1">The first parameter type to memoize</typeparam> /// <typeparam name="TParam2">The second parameter type to memoize</typeparam> /// <param name="func">the function to evaluate</param> /// <returns>A memoized value</returns> public static Func <TParam1, TParam2, TResult> AsMemoized <TParam1, TParam2, TResult>(this Func <TParam1, TParam2, TResult> func) { Dictionary <CachedTuple <TParam1, TParam2>, TResult> values = new Dictionary <CachedTuple <TParam1, TParam2>, TResult>(CachedTuple <TParam1, TParam2> .Comparer); return((arg1, arg2) => { var tuple = CachedTuple.Create(arg1, arg2); TResult value; if (!values.TryGetValue(tuple, out value)) { value = values[tuple] = func(arg1, arg2); } return value; }); }
public int GetHashCode(CachedTuple <T1, T2> obj) { return(obj._cachedHashCode); }
public bool Equals(CachedTuple <T1, T2> x, CachedTuple <T1, T2> y) { return(InternalEquals(x, y)); }