I was refactoring some code the other day, and I noticed that at one point, there was code that created a foreach loop, but it was keeping track of an index inside, by manually incrementing at the end of the foreach loop. Something like this:
int index = 0;
foreach (Widget widget in WidgetBasket)
// Do stuff…
index += 1;
Well, being the foolhardy coder that I was, I said let’s just change that foreach loop to a for loop, so we can keep track of the index as a part of the loop construct. I’ve done this a thousand times, so I didn’t think much of it. I also didn’t take a minute to look at the data type of Widget, not that it would have helped at that point.
So, I threw my code into test, and lo and behold I started getting null reference exceptions. What the heck – all I did was change a little loop?!?
Well, I dove under the covers, and it only took me a few minutes to find the issue. The Widget object was of type HybridDictionary. If you’re not familiar with a HybridDictionary, it’s one of those built-for-speed collection types, behaving like aListDictionary when it’s small, and switching over to a HashTable when it gets larger. Like all collections I’m aware of, it has an array-style indexer, which enables it’s use in looping constructs.
The rub with HybridDictionaries is that they don’t behave like 0-based indexed array – a foreach will keep returning the next found item until it’s done, but a for loop doesn’t behave like that – the 0th element was null, and so was the 1st, and so on. So, obviously, it’s not a good idea to go with a for loop – they just don’t work.
Thankfully, there is a way to have the HybridDictionary behave normally, but it comes at a performance cost that probably destroys the value of this type of collection in many common uses. You’d just call the CopyTo method, which will copy the dictionary to a one-dimensional, zero-based Array. That’s not all that intuitive, and it’s a trap I bet a lot of people fall into when starting to work with the HybridDictionary.
Given all this mess, I’m not a big fan of the HybridDictionary – give me a generic list any day!