The other day while reading a book on JavaScript I came across an interesting pattern known as memoization. Basically the purpose of this pattern is to cache the results of function execution so that only one unique parameter set needs to be evaluated. This of course will greatly speed up the execution of a function that repeatedly calculates the same value.
Today I came upon the need to populate a property of a list of objects where the property was set based on a value in the database. A simple example of this would be if you have a list of ids and some of those ids were duplicates. If you did this the plain vanilla way you would end up getting the same results from the database multiple times, because the id of what you are fetching appears multiple times.
I guess you could setup some sort of caching layer and deal with all the issues that has, but that seemed like way too much work. What I really wanted was a way to cache the results, but only while in the current scope. I figured that would be sufficient for my needs and keep things simple. Here is what I came up with.
The usage is like so.
1
2 var todo = new List<int> { 1, 2, 3, 1, 3, 2, 3, 4, 2, 3 };
3
4 var func = new MemoizedFunction<int, string>(GetData);
5 var results = new List<string>();
6
7 foreach (var t in todo)
8 results.Add(func.Execute(t));
9
Here is the implementation of the MemoizedFunction class.
1
2 class MemoizedFunction<TVal,TRet>
3 {
4 // Dictionary to hold already calculated values.
5 private Dictionary<TVal, TRet> memo = new Dictionary<TVal, TRet>();
6
7 // Function to be executed.
8 private Func<TVal,TRet> func = null;
9
10 public MemoizedFunction(Func<TVal,TRet> func)
11 {
12 this.func = func;
13 }
14
15 public TRet Execute(TVal val)
16 {
17 // If the value has not been calculated add it to the dictionary.
18 if (!memo.ContainsKey(val))
19 memo.Add(val, func(val));
20
21 // Return the value from the dictionary.
22 return memo[val];
23 }
24 }
25
You can see that the function is passed into the constructor and then the Execute method is called for each evaluation. Once the evaluation is complete, it is stored in a dictionary. In the future, if the parameter matches what is stored then you will just get the result. Like I said the beauty of this approach is that you get caching of the evaluation only while the “func” object, in the first set of code, is in scope. This way I never have to worry about expiring the cache and other complexity. I get greatly improved performance and the usage AND implementation is very straight forward and simple. Of course because it is simple you could customize the MemoizedFunction class to meet your individual parameter needs. I hope this makes sense. If not please leave a comment.