Cześć czy poniższemu kodowi czegoś brakuje, lub coś jest nie tak wg Was?
Chodziło mi o kaszowanie wyników z metody która przyjmuje dwa argumenty
wywołany kasz może być synchronicznie i asynchronicznie

z góry dziękuję za opinie

public class MemoryCache<TFirst, TSecond, TReturn>
    {
        private readonly ConcurrentDictionary<string, TaskCompletionSource<TReturn>> _sourceCache =
            new ConcurrentDictionary<string, TaskCompletionSource<TReturn>>();

        public bool ItemExists(string key)
        {
            return _sourceCache.ContainsKey(key);
        }

        public async Task<TReturn> AddOrGetItemAsync(string key, TFirst arg1, TSecond arg2, Func<TFirst, TSecond, Task<TReturn>> valueFactory)
        {
            var newSource = new TaskCompletionSource<TReturn>();
            var currentSource = _sourceCache.GetOrAdd(key, newSource);

            if (currentSource != newSource)
            {
                return await currentSource.Task;
            }

            try
            {
                var result = await valueFactory(arg1, arg2);
                newSource.SetResult(result);
            }
            catch (Exception e)
            {
                newSource.SetException(e);
            }

            return await newSource.Task;
        }

        public TReturn AddOrGetItem(string key, TFirst arg1, TSecond arg2, Func<TFirst, TSecond, TReturn> valueFactory)
        {
            var newSource = new TaskCompletionSource<TReturn>();
            var currentSource = _sourceCache.GetOrAdd(key, newSource);

            if (currentSource != newSource)
            {
                return currentSource.Task.Result;
            }

            try
            {
                var result = valueFactory(arg1, arg2);
                newSource.SetResult(result);
            }
            catch (Exception e)
            {
                newSource.SetException(e);
            }

            return newSource.Task.Result;
        }

        public bool TryUpdateItem(string key, TReturn value)
        {
            try
            {
                var newSource = new TaskCompletionSource<TReturn>();
                newSource.SetResult(value);

                _sourceCache[key] = newSource;
            }
            catch (KeyNotFoundException)
            {
                return false;
            }
            catch (ArgumentNullException)
            {
                return false;
            }

            return true;
        }
    }