I came across an interesting bug when working with a dictionary. I had a class using a dictionary as internal storage which should always ignore
the casing of key when access the dictionary, Similar to the following code:
[Serializable]
public class TestContainer
{
private readonly string id;
private readonly Dictionary<string, string> dictionary;
public TestContainer(string id)
{
this.id = id;
this.dictionary =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
public string GetValue(string key)
{
return this.dictionary[key];
}
public void AddValue(string key, string value)
{
this.dictionary.Add(key, value);
}
}
There were unit tests checking all possible scenarios to make sure the values were always retrieved correctly (at least I thought so). The container was serialized and saved
to a database by one application and deserialized by another application. The following sample has the same effect:
DataContractSerializer serializer = new DataContractSerializer(typeof(TestContainer));
using (MemoryStream memoryStream = new MemoryStream())
{
serializer.WriteObject(memoryStream, testcontainer);
memoryStream.Position = 0;
deserializedTestContainer = (TestContainer)serializer.ReadObject(memoryStream);
}
Everything seemed to work just fine, until I encountered a bug where a value in the dictionary couldn't be found. I looked at the serialized xml (which was quite a pain being
several MB big) and debugged to find the missing value. When I found the value in the dictionary I was really surprised and couldn't explain it. Then I realized the casing
of the key wasn't consistent and began to wonder whether I had missed a scenario in my unit tests. But everything seemed to be covered and all tests passed. While inspecting
the dictionary object I discovered that the dictionary's comparer was a GenericEqualityComparer
. That means the (de-)serialization ignores the comparer
of a dictionary and resets it to the default. To fix the issue, the [OnDeserialized]
attribute can be used:
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
this.dictionary = new Dictionary<string, string>(
this.dictionary, StringComparer.OrdinalIgnoreCase);
}
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.