diff --git a/FastCache/FastCache.cs b/FastCache/FastCache.cs index 5dad6b8..9ea45ab 100644 --- a/FastCache/FastCache.cs +++ b/FastCache/FastCache.cs @@ -173,13 +173,7 @@ public bool TryAdd(TKey key, TValue value, TimeSpan ttl) return _dict.TryAdd(key, new TtlValue(value, ttl)); } - /// - /// Adds a key/value pair by using the specified function if the key does not already exist, or returns the existing value if the key exists. - /// - /// The key to add - /// The factory function used to generate the item for the key - /// TTL of the item - public TValue GetOrAdd(TKey key, Func valueFactory, TimeSpan ttl) + private TValue GetOrAddCore(TKey key, Func valueFactory, TimeSpan ttl) { bool wasAdded = false; //flag to indicate "add vs get". TODO: wrap in ref type some day to avoid captures/closures var ttlValue = _dict.GetOrAdd( @@ -187,19 +181,28 @@ public TValue GetOrAdd(TKey key, Func valueFactory, TimeSpan ttl) (k) => { wasAdded = true; - return new TtlValue(valueFactory(k), ttl); + return new TtlValue(valueFactory(), ttl); }); //if the item is expired, update value and TTL //since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups) if (!wasAdded) //performance hack: skip expiration check if a brand item was just added { - ttlValue.ModifyIfExpired(() => valueFactory(key), ttl); + ttlValue.ModifyIfExpired(valueFactory, ttl); } return ttlValue.Value; } + /// + /// Adds a key/value pair by using the specified function if the key does not already exist, or returns the existing value if the key exists. + /// + /// The key to add + /// The factory function used to generate the item for the key + /// TTL of the item + public TValue GetOrAdd(TKey key, Func valueFactory, TimeSpan ttl) + => GetOrAddCore(key, () => valueFactory(key), ttl); + /// /// Adds a key/value pair by using the specified function if the key does not already exist, or returns the existing value if the key exists. /// @@ -208,25 +211,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory, TimeSpan ttl) /// TTL of the item /// Argument value to pass into valueFactory public TValue GetOrAdd(TKey key, Func valueFactory, TimeSpan ttl, TArg factoryArgument) - { - bool wasAdded = false; //flag to indicate "add vs get" - var ttlValue = _dict.GetOrAdd( - key, - (k) => - { - wasAdded = true; - return new TtlValue(valueFactory(k, factoryArgument), ttl); - }); - - //if the item is expired, update value and TTL - //since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups) - if (!wasAdded) //performance hack: skip expiration check if a brand item was just added - { - ttlValue.ModifyIfExpired(() => valueFactory(key, factoryArgument), ttl); - } - - return ttlValue.Value; - } + => GetOrAddCore(key, () => valueFactory(key, factoryArgument), ttl); /// /// Adds a key/value pair by using the specified function if the key does not already exist, or returns the existing value if the key exists. @@ -235,24 +220,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory, Ti /// The value to add /// TTL of the item public TValue GetOrAdd(TKey key, TValue value, TimeSpan ttl) - { - bool wasAdded = false; //flag to indicate "add vs get" - var ttlValue = _dict.GetOrAdd(key, - (k) => - { - wasAdded = true; - return new TtlValue(value, ttl); - }); - - //if the item is expired, update value and TTL - //since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups) - if (!wasAdded) //performance hack: skip expiration check if a brand item was just added - { - ttlValue.ModifyIfExpired(() => value, ttl); - } - - return ttlValue.Value; - } + => GetOrAddCore(key, () => value, ttl); /// /// Tries to remove item with the specified key