A simple extension method, but a beautiful one
This came up a little while in a newsgroup question, and Marc Gravell and I worked out a solution between us. I've finally included it in MiscUtil (although not released it yet - there's a lot of stuff ready to go when we've finalised namespaces and updated the website etc) but I thought I'd share it here.
How often have you written code to do something like counting word frequencies, or grouping items into lists? I know a lot of this can be solved with LINQ if you're using .NET 3.5, but in .NET 2.0 we've always been nearly there. Dictionaries have provided a lot of the necessary facilities, but there's always the bit of code which needs to check whether or not we've already seen the key, and populate the dictionary with a suitable initial value if not - a count of 0, or an empty list for example.
There's something that 0 and "empty list" have in common. They're both the results of calling new TValue() for their respect TValue types of int and List<Whatever>. Can you see what's coming? A generic extension method for dictionaries whose values are of a type which can use a parameterless constructor, which returns the value associated with a key if there is one, or a new value (which is also inserted into the dictionary) otherwise. It's really simple, but it'll avoid duplication all over the place:
Note: This code has been updated due to comments below. Comments saying "Use TryGetValue" referred to the old version!
public static TValue GetOrCreate<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
TKey key)
where TValue : new()
{
TValue ret;
if (!dictionary.TryGetValue(key, out ret))
{
ret = new TValue();
dictionary[key] = ret;
}
return ret;
}
The usage of it might look something like this:
var dict = new Dictionary<string,int>();
foreach (string word in someText)
{
dict[word] = dict.GetOrCreate(word)+1;
}
I'm not going to claim this will set the world on fire, but I know I'm fed up with writing the kind of code which is in GetOrCreate, and maybe you are too.
Additional overloads are available to specify either a value to use when the key is missing, or a delegate to invoke to create a value.