[Mono-dev] Key matching issue in generic Dictionary [correct message]

Generic 2006 generic2006 at libero.it
Wed Aug 23 10:17:59 EDT 2006


Hi all

I'm facing a strange behavior affecting System.Collections.Generic.Dictionary<TKey,TValue>: when I try to search for a key among the dictionary entries using interface members such as ContainsKey(<TKey> key) or this[<TKey> key] I receive wrong responses (the key can't be find, whilst it's really there!).
I supposed that it could be a problem on the TKey side (where I implemented System.IEquatable<TKey>), so I put some Console.WriteLine()
inside the code to verify. A System.Collections.Generic.Dictionary instance is incapsulated in MyDictionary (an implementation of generic IDictionary), TKey is assigned to Name type, TValue is irrelevant.

class Name : IEquatable<Name>
{
 public Name(string value)
 {
  ...
 }

 public bool Equals(Name obj)
 {
  Console.WriteLine("Name.Equals(): this: " + this.value + " other: " + obj.Value);
  return this.value.Equals(obj.Value);
 }

 public string Value
 {
  get{return this.value;}
 }
}

class MyDictionary : IDictionary<Name,Object>
{
 protected Dictionary<Name,Object> entries = new Dictionary<Name,Object>();

...
 public bool ContainsKey(Name key)
 {
  Console.WriteLine("MyDictionary.ContainsKey: key = " + key.Value);
  return this.entries.ContainsKey(key);
 }

 public Object this[Name key]
 {
  get
  {
   try
   {
    Console.WriteLine("Dictionary[]: key = " + key.Value);
    return ((Object) this.entries[key]);
   }
   catch(Exception e)
   {
    Console.WriteLine("Dictionary[]:exception: " + e.Message);
    foreach(KeyValuePair<PdfName,Object> kv in this.entries)
    {
     Console.WriteLine("PdfDictionary[]: pair: key = " + kv.Key.Value + " equals : " + key.Equals(kv.Key));
    }
    return null;
   }
  }
 }
...
}

Here's the test I made:
1) populate MyDictionary with 3 entry pairs, whose keys are: Name("Info"), Name("Root"), Name("Size");
2) try to find Name("Encrypt") among MyDictionary keys, invoking MyDictionary.ContainsKey(Name key) method and obtaining such console output:
MyDictionary.ContainsKey: key = Encrypt
Name.Equals(): this: Encrypt other: Info
Name.Equals(): this: Encrypt other: Root
3) as you can see from the previous step, it strangely missed to invoke Name.Equals for the Name("Size") instance (just considered Name("Info") and Name("Root"): why?
4) try to get the object related to the Name("Size") key invoking MyDictionary.this[Name key] method and obtaining such console output:
Dictionary[]: key = Size
Dictionary[]:exception: The given key was not present in the dictionary.
Name.Equals(): this: Size other: Info
Dictionary[]: pair: key = Info equals : False
Name.Equals(): this: Size other: Root
Dictionary[]: pair: key = Root equals : False
Name.Equals(): this: Size other: Size
Dictionary[]: pair: key = Size equals : True
5) as you can see from the previous step, before the exception message there is NO invocation to Name.Equals() method, despite the invocation to this.entries[key] which should trigger the equality comparison. Then the iteration through all the keys yelds the expected result (Name("Size") key exists and is positively equated -- so the problem is NOT in IEquatable<Name> implementation!).

So, the problem seems to be that System.Collections.Generic.Dictionary<TKey,TValue> has a faulty way to access its keys...
What do you suggest about it?
Is it a reported bug?
How can I obtain the correct behavior?

Many thanks




More information about the Mono-devel-list mailing list