I have a concurrent dictionary which maps an array of characters to an integer
var dictionary = new ConcurrentDictionary<char[], int>();
It works fine if I map an array
var key = new char[] { 'A', 'B' };
var value = 8;
dictionary.TryAdd(key, value);
Console.WriteLine(dictionary[key]);
gives
8
But if I use an array created from a queue it doesn’t work
var qu = new Queue<char>();
qu.Enqueue('A');
qu.Enqueue('B');
Console.WriteLine(dictionary[qu.ToArray()]);
gives
Unhandled exception. System.Collections.Generic.KeyNotFoundException: The given key 'System.Char[]' was not present in the dictionary.
at System.Collections.Concurrent.ConcurrentDictionary`2.ThrowKeyNotFoundException(TKey key)
at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key)
at Program.<Main>$(String[] args) in C:\Users\User\Desktop\SubstitutionCipher\Program.cs:line 65
C:\Users\User\Desktop\SubstitutionCipher\bin\Debug\net6.0\SubstitutionCipher.exe (process 18688) exited with code -532462766.
What is wrong and how to fix it?
>Solution :
In order to find the item in the dictionary, the dictionary gets a hash code and does an equality check. For the char-arrays, this leads to a reference comparison. Even though the arrays do contain the same items, they are different objects, so the reference comparison fails. Hence, the item is not found.
There are several ways to solve this:
- Either you help the dictionary to find the item by implementing a custom equality comparer – that is a class that implements
IEqualityComparer<T>and is used as a constructor parameter when creating the dictionary. - Or you use a type that already implements a comparison that fits your needs. In the case of a
char-Array, you could use astringas a simple alternative, e.g.
var key = new string(new char[] { 'A', 'B' });
var value = 8;
dictionary.TryAdd(key, value);
Console.WriteLine(dictionary[key]);
var qu = new Queue<char>();
qu.Enqueue('A');
qu.Enqueue('B');
key = new string(qu.ToArray());
Console.WriteLine(dictionary[key]);
See this fiddle to test.