Exploring ShadeTree Features, Part 2: Cache<KEY, VALUE>

Or, as I like to call it: "That stupid dictionary thing we’ve all written a thousand times but were too lazy to component-ize for reuse"

How many times have you written code like this in your C# 2.0-and-later life?

Foo foo = null;

if( ! fooCache.TryGetValue(key, out foo))
    foo = new Foo();
    fooCache.Add(foo.Key, foo);

return foo

Well, no more!  Enter ShadeTree.Core.Cache!

Nifty features:

  1. Automatic cache miss value creation: When you attempt to get an item from the cache that’s not there, if configured to do so, it’ll new one up for you, add it, and return it.
  2. Quiet Add: Call the Store method to add an item if it’s not already added (otherwise, it’ll do nothing)
  3. Quiet Remove: Remove won’t throw an error if the item isn’t in the Cache
  4. Each(): Handy lambda-friendly version of ‘for each’
  5. Exists(): Handy lambda-friendly version of TryGetValue

Cache Miss Handling Example

This one I particularly like, especially when you need something like this: Dictionary<string, IList<Foo>>.

Consider this example: We want to have a Cache<string, IList<Foo>>.  We want to add a new key "Blah" and add a new Foo to it’s list.

With Dictionary<T,U>, you have to do something like:

Dictionary<string, IList<Foo>> dict = new Dictionary<string, IList<Foo>>();

IList<Foo> fooList = null;

if( ! dict.ContainsKey("Blah") )
    fooList = new List<Foo>();
    dict.Add("Blah", fooList);

fooList.Add(new Foo());

But with Cache, it’s much simpler:

Cache<string, IList<Foo>> cache = new Cache<string, IList<Foo>>(k => new List<Foo>());
cache.Get("Blah").Add(new Foo());

The trick is that little lambda expression (k => new List<Foo>()).  When the call to Get("Blah") fails to find anything in the underlying dictionary, it’ll add a new entry to the dictionary with key "Blah" and the result of that lambda expression (i.e. a new List<Foo>).

About Chad Myers

Chad Myers is the Director of Development for Dovetail Software, in Austin, TX, where he leads a premiere software team building complex enterprise software products. Chad is a .NET software developer specializing in enterprise software designs and architectures. He has over 12 years of software development experience and a proven track record of Agile, test-driven project leadership using both Microsoft and open source tools. He is a community leader who speaks at the Austin .NET User's Group, the ADNUG Code Camp, and participates in various development communities and open source projects.
This entry was posted in .NET, ShadeTree. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Someone has been using the Ruby Hash recently… yeah? :)

  • Avish

    This is awesome and much needed, but I think the naming is inappropriate. What is it about it that makes it a cache? Seems like a dictionary with a default new item behavior. In python they call it a defaultdict, if I’m not mistaken. Please consider renaming this to correctly reveal its intention, as “Cache” is very vague for a general-purpose utility such as this.

  • @Avrish: Yeah, I thought that, too. Cache is a much overloaded word.

    Keep in mind, this is an open source project, so I strongly encourage you to make the change and submit a patch (sure, it’s a breaking change, but it’s not that big of a deal at this point). We’d love to have more contributors to ShadeTree (hint hint)! :)