public static Func <CancellationToken, TParam, Task <TResult> > AsMemoized <TParam, TResult>(this Func <CancellationToken, TParam, Task <TResult> > func) { var values = new SynchronizedDictionary <TParam, Func <CancellationToken, Task <TResult> > >(); // It's safe to use default(TParam) as this won't get called anyway if TParam is a vlue type. var nullValue = Funcs.CreateAsyncMemoized(ct => func(ct, default(TParam))); return((ct, param) => { if (param == null) { return nullValue(ct); } else { var memoizedFunc = values.FindOrCreate(param, () => Funcs.CreateMemoized(c => func(c, param))); return memoizedFunc(ct); } }); }