Skip to content

Commit 262a663

Browse files
committed
Refactor GetOrAdd methods to reduce duplication
1 parent 1149517 commit 262a663

File tree

1 file changed

+14
-46
lines changed

1 file changed

+14
-46
lines changed

FastCache/FastCache.cs

Lines changed: 14 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -173,33 +173,36 @@ public bool TryAdd(TKey key, TValue value, TimeSpan ttl)
173173
return _dict.TryAdd(key, new TtlValue(value, ttl));
174174
}
175175

176-
/// <summary>
177-
/// 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.
178-
/// </summary>
179-
/// <param name="key">The key to add</param>
180-
/// <param name="valueFactory">The factory function used to generate the item for the key</param>
181-
/// <param name="ttl">TTL of the item</param>
182-
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
176+
private TValue GetOrAddCore(TKey key, Func<TValue> valueFactory, TimeSpan ttl)
183177
{
184178
bool wasAdded = false; //flag to indicate "add vs get". TODO: wrap in ref type some day to avoid captures/closures
185179
var ttlValue = _dict.GetOrAdd(
186180
key,
187181
(k) =>
188182
{
189183
wasAdded = true;
190-
return new TtlValue(valueFactory(k), ttl);
184+
return new TtlValue(valueFactory(), ttl);
191185
});
192186

193187
//if the item is expired, update value and TTL
194188
//since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups)
195189
if (!wasAdded) //performance hack: skip expiration check if a brand item was just added
196190
{
197-
ttlValue.ModifyIfExpired(() => valueFactory(key), ttl);
191+
ttlValue.ModifyIfExpired(valueFactory, ttl);
198192
}
199193

200194
return ttlValue.Value;
201195
}
202196

197+
/// <summary>
198+
/// 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.
199+
/// </summary>
200+
/// <param name="key">The key to add</param>
201+
/// <param name="valueFactory">The factory function used to generate the item for the key</param>
202+
/// <param name="ttl">TTL of the item</param>
203+
public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
204+
=> GetOrAddCore(key, () => valueFactory(key), ttl);
205+
203206
/// <summary>
204207
/// 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.
205208
/// </summary>
@@ -208,25 +211,7 @@ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory, TimeSpan ttl)
208211
/// <param name="ttl">TTL of the item</param>
209212
/// <param name="factoryArgument">Argument value to pass into valueFactory</param>
210213
public TValue GetOrAdd<TArg>(TKey key, Func<TKey, TArg, TValue> valueFactory, TimeSpan ttl, TArg factoryArgument)
211-
{
212-
bool wasAdded = false; //flag to indicate "add vs get"
213-
var ttlValue = _dict.GetOrAdd(
214-
key,
215-
(k) =>
216-
{
217-
wasAdded = true;
218-
return new TtlValue(valueFactory(k, factoryArgument), ttl);
219-
});
220-
221-
//if the item is expired, update value and TTL
222-
//since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups)
223-
if (!wasAdded) //performance hack: skip expiration check if a brand item was just added
224-
{
225-
ttlValue.ModifyIfExpired(() => valueFactory(key, factoryArgument), ttl);
226-
}
227-
228-
return ttlValue.Value;
229-
}
214+
=> GetOrAddCore(key, () => valueFactory(key, factoryArgument), ttl);
230215

231216
/// <summary>
232217
/// 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<TArg>(TKey key, Func<TKey, TArg, TValue> valueFactory, Ti
235220
/// <param name="value">The value to add</param>
236221
/// <param name="ttl">TTL of the item</param>
237222
public TValue GetOrAdd(TKey key, TValue value, TimeSpan ttl)
238-
{
239-
bool wasAdded = false; //flag to indicate "add vs get"
240-
var ttlValue = _dict.GetOrAdd(key,
241-
(k) =>
242-
{
243-
wasAdded = true;
244-
return new TtlValue(value, ttl);
245-
});
246-
247-
//if the item is expired, update value and TTL
248-
//since TtlValue is a reference type we can update its properties in-place, instead of removing and re-adding to the dictionary (extra lookups)
249-
if (!wasAdded) //performance hack: skip expiration check if a brand item was just added
250-
{
251-
ttlValue.ModifyIfExpired(() => value, ttl);
252-
}
253-
254-
return ttlValue.Value;
255-
}
223+
=> GetOrAddCore(key, () => value, ttl);
256224

257225
/// <summary>
258226
/// Tries to remove item with the specified key

0 commit comments

Comments
 (0)