74

I have a Dictionary<string, object> dictionary. It used to be Dictionary<Guid, object> but other 'identifiers' have come into play and the Keys are now handled as strings.

The issue is that the Guid keys from my source data are coming as VarChar, so now a key of "923D81A0-7B71-438d-8160-A524EA7EFA5E" is not the same as "923d81a0-7b71-438d-8160-a524ea7efa5e" (wasn't a problem when using Guids).

What's really nice (and sweet) about the .NET framework is that I can do this:

Dictionary<string, CustomClass> _recordSet = new Dictionary<string, CustomClass>(
    StringComparer.InvariantCultureIgnoreCase);

And that works great. But what about a nested Dictionary? Like the following:

Dictionary<int, Dictionary<string, CustomClass>> _customRecordSet 
    = new  Dictionary<int, Dictionary<string, CustomClass>>();

How would I specify the string comparer on a nested dictionary like this?

Ivaylo Slavov
  • 8,179
  • 10
  • 57
  • 103
MoSlo
  • 2,650
  • 3
  • 30
  • 36
  • 26
    Just a hint, you may want to reconsider the use of `StringComparer.InvariantCultureIgnoreCase`. This comparer is slow, as it would compare strings using character classes to overcome cross-cultural differences. This means that the word `Straße` will be treated as equal to `Strasse` and vice-versa. I am assuming you do not want such behavior and if performance is crucial (if you are implementing something like a cache layer over a database) then you'd be better off by using `StringComparer.OrdinalIgnoreCase`. The ordinal comparer is the fastest string comparer the .NET framework can offer. – Ivaylo Slavov May 13 '14 at 12:48
  • 3
    Possible duplicate of [Case insensitive access for generic dictionary](http://stackoverflow.com/questions/13230414/case-insensitive-access-for-generic-dictionary) – avs099 Oct 09 '15 at 21:06
  • 2
    Really @avs099? That post you've linked to is a year younger than this one. Did you even notice? – AustinWBryan Jan 06 '16 at 13:25
  • 3
    @AustinWBryan: "Possible duplicate" is a way to clean-up - to close similar questions and keep one with the best answers. The date is not essential. See [Should I vote to close a duplicate question, even though it's much newer, and has more up to date answers?](http://meta.stackexchange.com/q/147643) – Michael Freidgeim Aug 08 '16 at 03:51
  • Related post - [Case-INsensitive Dictionary with string key-type in C#](https://stackoverflow.com/q/13988643/465053) – RBT Apr 06 '18 at 11:33

2 Answers2

80

When you add an element to the outer dictionary, you'll likely create a new instance of the nested dictionary, add it at this point, making use of the overloaded constructor that takes an IEqualityComparer<TKey>.

_customRecordSet.Add(0, new Dictionary<string, CustomClass>(StringComparer.InvariantCultureIgnoreCase));


Update 08/03/2017: Anecdotally, I read somewhere (I think in "Writing High-Performance .NET Code") that StringComparer.OrdinalIgnoreCase is more efficient when simply wanting to disregard the case of characters. This, however, is entirely unfounded by myself so YMMV.

Adam Houldsworth
  • 60,104
  • 9
  • 137
  • 177
8

You are going to have to initialize the nested dictionaries in order to use them. Just use the code you have above at that point.

Basically, you should have some code like this:

public void insert(int int_key, string guid, CustomClass obj)
{
    if (_customRecordSet.ContainsKey(int_key)
         _customRecordSet[int_key][guid] = obj;
    else
    {
         _customRecordSet[int_key] = new Dictionary<string, CustomClass> 
                                     (StringComparer.InvariantCultureIgnoreCase);
         _customRecordSet[int_key][guid] = obj;
    }
}
Patrick
  • 1,128
  • 7
  • 13