Is there a way to unify or refactor two methods that do basically the same but the difference being of handling a type of object or a collection of the same type of object?
The following is an implementation of two methods that have very similar behavior. They handle a cache for an API, so when someone asks for a value or a set of values, it verifies that the entry is in cache already. If not, they call the method that will return from an external API: a value or a set of values. Finally the methods, update the cache and return the value/values.
public async Task<T> GetValue<T>(string cacheKey, Func<Task<T>> getItem, MemoryCacheEntryOptions memoryCacheEntryOptions = null)
{
if (_memoryCache.TryGetValue(cacheKey, out T cacheEntry))
{
return cacheEntry;
}
else
{
cacheEntry = await getItem();
return SetValue(cacheKey, cacheEntry, memoryCacheEntryOptions);
}
}
public async Task<IList<T>> GetValues<T>(string cacheKey, Func<Task<IList<T>>> getItems, MemoryCacheEntryOptions memoryCacheEntryOptions = null)
{
if (_memoryCache.TryGetValue(cacheKey, out IList<T> cacheEntries))
{
return cacheEntries;
}
else
{
cacheEntries = await getItems();
return SetValues(cacheKey, cacheEntries, memoryCacheEntryOptions);
}
}
public async Task<T> GetValue<T>(string cacheKey, Func<Task<T>> getItem, MemoryCacheEntryOptions memoryCacheEntryOptions = null) => _memoryCache.TryGetValue(cacheKey, out T cacheEntry) ? cacheEntry : SetValue(cacheKey, await getItem(), memoryCacheEntryOptions);
\$\endgroup\$GetValue<T>
would be enough, as it can do the job forGetValues<T>
, look:public Task<IList<T>> GetValues<T>(string cacheKey, Func<Task<IList<T>>> getItems, MemoryCacheEntryOptions memoryCacheEntryOptions = null) => GetValue(cacheKey, getItems, memoryCacheEntryOptions);
\$\endgroup\$T
isn't a type name but like a placeholder for any real type. With generic type you tell compiler "I don't know the real type but it will be the same type here, here and here". T and T is the same type, the same forList<T>
. But you can drop details aboutIList
because you don't use the interface methods whichIList
provides. ThenIList
can be just aT
. \$\endgroup\$