Frans Bouma's blog

Generator.CreateCoolTool();

Syndication

News



    Visit LLBLGen Pro's website

    Follow me on Twitter

    Add to Technorati Favorites

About me

Fun stuff I created

My work

(.NET 2.) Dictionary(Of Key, Value) performance trick

(I used the VB.NET notation in the title so it won't nag about illegal characters like < and >)

In .NET 2.0 you'll have this new generic Hashtable variant called Dictionary<TKey, TValue>. It can be used as a Hashtable but now strongly typed and it doesn't use boxing anymore with value types. That's great and all, though there's one thing that's different from the hashtable: retrieving a value with a key that's not there. If the key value isn't present in the Dictionary, you'll get an exception when you do:

MyClass myValue = myDictionary[key];
and key is not present in myDictionary, while with the hashtable, you'll get back a null value. See my old blogpost about that.

What's often overlooked is a performance penalty with this pattern shift. Because of the exception, people will do something like this:

MyClass toReturn;
if(!_myDictionary.ContainsKey(key))
{
	toReturn = _myDictionary[key];
}
else
{
	toReturn = new MyClass();
}
Pretty obvious code, right? Well, ok, but it has a performance penalty which isn't that obvious: you'll query the key index twice: once in the ContainsKey call and once in the _myDictionary[key] call. If you query your dictionary a lot of times, even if the dictionary is fairly small, it will hurt performance. Better do:
MyClass toReturn = null;
if(!_myDictionary.TryGetValue(key, out toReturn))
{
	toReturn = new MyClass();
}
During profile sessions of my code I found a lot of these misusages in my .NET 2.0 versions of ported .NET 1.1 code. So, be smart, and do it right the first time with TryGetValue, it's your friend.

About the lack of blogging lately: I was very busy with finalizing the beta for LLBLGen Pro v2.0, which first beta was released 2 days ago. It's still pretty hectic, but I hope to have more time soon to blog more!

Published Tuesday, May 02, 2006 10:52 AM by FransBouma

Filed under:

Comments

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Thursday, May 04, 2006 1:32 PM

That sucks. I hadn't noticed that yet. I usually have some code like:
Customer cust = (Customer)customers[custName];
if (cust!=null)
...
The whole try thing with an out parameter is so much more verbose. And it makes upgrading to use generic hashtables a heck of a lot more work.

John Wood

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Monday, May 08, 2006 12:00 AM

Nice tip! I didn't notice this has a performance impact. Now i have to do some refactoring. ;-)

Chris Ongsuco

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Wednesday, May 17, 2006 8:17 AM

PowerCollections.NET (Which I wouln't consider living without) extends this with a GetValueElseAdd operation, which is often really what you're looking to do in this instance.

(It's missing on some containers, for reasons I cant quite fathom, but it can be implemented on those by using View. I must ask on the PC.NET forum why this is.)

Ruben Bartelink

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Monday, July 10, 2006 2:19 PM

I have a dictionary declared like this. Dictionary^ controlPool = gcnew Dictionary(); controlPool->Add("PFWUtilities",tools); then later on I have: PFWUtilities^ tools; passedControls->TryGetValue("PFWUtilities",tools) tools never gets any value. I'm using c++/cli. It compiles fine but the value never comes through. Any ideas?

Todd

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Monday, July 10, 2006 2:40 PM

I tried this as well... no luck passedControls->TryGetValue("PFWUtilities", static_cast(tools));

Todd

# re: (.NET 2.) Dictionary(Of Key, Value) performance trick@ Monday, July 10, 2006 2:41 PM

What I have to do to get the value is this: tools = static_cast(passedControls["PFWUtilities"]); but I lose the benefit of the trygetvalue. Anyone have any ideas?

Todd