Just to avoid reinventing the wheel
I'm wondering whether a standard C# implementation already exists to cache the results from a long-running, resource-intensive method.
To my mind, the Lazy<T>
would be appropriate, but unfortunately it seems to lack the input parameter to index the result.
I hope the following helps to clarify: this is my custom solution.
public class Cached<FromT,ToT>
{
private Func<FromT,ToT> _my_func;
private Dictionary<FromT,ToT> funcDict;
public Cached(Func<FromT,ToT> coreFunc, IEqualityComparer<FromT> comparer = null)
{
_my_func = coreFunc;
if (comparer != null) {
funcDict = new Dictionary<FromT,ToT>(comparer);
} else {
funcDict = new Dictionary<FromT,ToT>();
}
}
public ToT Get(FromT fromKey) {
if (!funcDict.ContainsKey(fromKey)) {
funcDict.Add(fromKey, _my_func(fromKey) );
}
return funcDict[fromKey];
}
}
Find below my unit-testing code.
string DBSimulation(int example, bool quick = false) {
if (!quick) Thread.Sleep(15000);
return example.ToString();
}
[Test]
public void Test03Cached() {
var testCache = new Functional.Cached<int,string>(x => DBSimulation(x));
DateTime checkNow = DateTime.Now;
string logResult = "";
for (int i = 0; i < 24; i++) {
Assert.AreEqual(DBSimulation( i % 3, true), testCache.Get( i % 3));
logResult += String.Format("After {0} seconds => {1} returned from {2} \n",
((TimeSpan)(DateTime.Now - checkNow)).TotalSeconds,
testCache.Get( i % 3), i);
}
Console.WriteLine(logResult);
double elapsed = ((TimeSpan)(DateTime.Now - checkNow)).TotalSeconds;
Assert.LessOrEqual(elapsed, 15*3+1,"cache not working, {0} seconds elapsed", elapsed);
}
with its output
After 15,0035002 seconds => 1 returned from 1
After 30,0050002 seconds => 2 returned from 2
After 45,0065002 seconds => 0 returned from 3
After 45,0065002 seconds => 1 returned from 4
After 45,0065002 seconds => 2 returned from 5
...
After 45,0065002 seconds => 0 returned from 21
After 45,0065002 seconds => 1 returned from 22
After 45,0065002 seconds => 2 returned from 23
Edit
For a generic FromT an IEqualityComparer is needed for the Dictionary