views:

75

answers:

1

In Wintellect's PowerCollections, there's a GetValueElseAdd which works like this:

if ( collection.GetValueElseAdd( key, ref value))
{
    // just added, value unmodified
}

Or

// factory method only gets called if the key is not present.
if ( collection.GetValueElseAdd( key, out value, () => thingFactory.CreateNew()))
{
    // just added; value contains factory result
}

In both cases, there's only one walk through the hashes to isolate where the value is going to sit. (See http://stackoverflow.com/questions/2138982/what-happens-to-c-dictionaryint-int-lookup-if-the-key-does-not-exist/2138988#2138988 for more discussion of the tradeoffs)

The question is, why has functionality like this not made it into the BCL, especially given that pretty much all of the rest of PowerCollections got sucked in via 3.5/LINQ and the new collections added in 4.0?

Is it because the general usage pattern is that one only does an Add once whereas you're generally only hitting the equivalent of the TryGetValue path with a single hashtable lookup the bulk of the time?

Is it because this is much more valuable in a tree than in a hashtable (could only find this implementation on the net but I think it was on more than just an OrderedList collection)

EDIT: See also the post linked in the comment's on Fredrik's response which discusses multithreading considerations for Sychronized variants of a collection.

Or is there another idiom I'm missing? If only Peter Golde was here!

+2  A: 

The only rationale that I can come up with that could potentially argue against a GetValueElseAdd is the Single Responsibility Principle. The method name indicates that the method has two responsibilities: it tries to get an item and, if it fails, adds the item (I never worked with the PowerCollections, but I will assume that value gets assigned with the created object in the case when the key is not found).

If I was designing the API this, together with the fact that the behavior is simple to create and encapsulate, would probably be enough to keep me from implementing it.

I usually try to take a step back as soon as method names start having words like And, Or, Else and such, as these for me are indicators that the method might have too many responsibilities.

Fredrik Mörk
+1 Well thought out response which I agree with. The reason for wanting it isnt just down to having a helper for a [not so] common idiom - its also the fact that there is a performance benefit to not having to do the "where does this go" analysis for the TryGet+Add path).
Ruben Bartelink
The other thing thats slightly ugly/incomplete about the syntax of GVEA is having a more complete and consistent set of overloads dealing with how the key is derived from the value, but again thats separate to why this doesnt exist given it should provide a perf benefit that cant otherwise be obtained (in the same way that `TryGet` has a perf benefit vs `ContainsKey` in the case of the key being present)
Ruben Bartelink
http://www.infoq.com/news/2010/01/CDS-Dictionary mentions a `GetOrAdd` and the hints at the myriad issues brought into play by calling a factory method via a method on a synced collection (which supports your SRP point)
Ruben Bartelink
@Ruben: Interesting points that highlights the difficulty in getting it right. I am (in the back of my head) pondering what a good extension method for `Dictionary<TKey, TValue>` would look like. Also, thanks for the edit. (I hope this question gets some more attention; would be nice to get more input on it).
Fredrik Mörk
I should have psoted later in the day. Some days people around here are far more interested in nonsense like http://stackoverflow.com/questions/658913/c-style-cast-from-unsigned-char-to-const-char/658915#658915 and http://stackoverflow.com/questions/2140258/which-dal-choice-should-i-use/2140368#2140368. I wonder what MiscUtil and the like have in terms of extension methods? (Here's hoping there's a Google Alert out on that keywork :P)
Ruben Bartelink
@Fredrik Mork: As you're half tracking this, wanted to point at [this post from Ayende](http://feedproxy.google.com/~r/AyendeRahien/~3/2qT1v0QpjFw/i-love-concurrentdictionary.aspx) in case you miss it
Ruben Bartelink