title: Cache Function results
body: <p>For fun, I'm playing with a class to easily cache function results.  The basic idea is that you can take any function you want &mdash; though you'd only want to use it for relatively expensive functions &mdash; and easily wrap it to use relatively inexpensive dictionary lookups for later runs with the same argument.  There's really not much to it:</p>
  
  <pre><code>public class AutoCache&lt;TKey, TValue&gt; 
  {  
      public AutoCache(Func&lt;TKey, TValue&gt; FunctionToCache)
      {
          _StoredFunction = FunctionToCache;
          _CachedData = new Dictionary&lt;TKey, TValue&gt;();
      }
  
      public TValue GetResult(TKey Key)
      {
          if (!_CachedData.ContainsKey(Key)) 
              _CachedData.Add(Key, _StoredFunction(Key));
          return _CachedData[Key];
      }
  
      public void InvalidateKey(TKey Key)
      {
          _CachedData.Remove(Key);
      }
  
      public void InvalidateAll()
      {
          _CachedData.Clear();
      }
  
      private Dictionary&lt;TKey, TValue&gt; _CachedData;
      private Func&lt;TKey, TValue&gt; _StoredFunction; 
  }
  </code></pre>
  
  <p>Unfortunately, there are some additional restrictions that make this much less useful than it could be.  There are also some features we could add and other considerations to the implementation.  I'm looking for thoughts on ways this can be improved for any of the following points:</p>
  
  <ul>
  <li>This requires a function that returns the same result for a given set of arguments (it must be stateless). Probably no way to change this.</li>
  <li>It's limited to a very narrow delegate range.  Could we expand it to easily work for any function that accepts at least one parameter and returns a value, perhaps by wrapping arguments in an anonymous type?  Or would we need an additional implemenation for each Func delegate we wanted to support?  If so, can we build an abstract class to make this easier?</li>
  <li>It's not thread-safe.</li>
  <li>No automatic invalidation.  This makes it dangerous for garbage collection.  You need to keep it around for a while for it to be useful, and that means you're not going to really ever discard old and potentially un-needed cache items.</li>
  <li>Can we inherit from this to make the cache bi-directional for the case where the function has a single argument?</li>
  </ul>
  
  <p>As a point of reference, if I ever use this in real code the most likely place I envision it is as part of a business logic layer, where I use this code to wrap a method in the data access layer that just pulls data from a lookup table.  In this case, the database trip would be expensive relative to the dictionary and there would almost always be exactly one 'key' value for the lookup, so it's a good match.</p>