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

2006-08-23 Thread Generic 2006
Hi all

I'm facing a strange behavior affecting 
System.Collections.Generic.DictionaryTKey,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.IEquatableTKey), 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 : IEquatableName
{
 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 : IDictionaryName,Object
{
 protected DictionaryName,Object entries = new DictionaryName,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(KeyValuePairPdfName,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 IEquatableName 
implementation!).

So, the problem seems to be that 
System.Collections.Generic.DictionaryTKey,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

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


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

2006-08-23 Thread Brian Crowell
Generic 2006 wrote:
 I'm facing a strange behavior affecting 
 System.Collections.Generic.DictionaryTKey,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.IEquatableTKey), 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.

IEquatableT is not enough. You need to override Object.GetHashCode() and 
Object.Equals(). IEquatableT is optional, GetHashCode and Equals are 
mandatory.

--Brian
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


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

2006-08-23 Thread Brian Crowell
Brian Crowell wrote:
 IEquatableT is not enough. You need to override Object.GetHashCode() and 
 Object.Equals(). IEquatableT is optional, GetHashCode and Equals are 
 mandatory.

Off the top of my head, this is the proper implementation:

class Name : IEquatableName
{
  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;}
  }

  public override bool Equals( object obj ) {
Name other = obj as Name;

if( other == null )
  return false;

return Equals(other);   // Calls Equals(Name obj)
  }

  public override int GetHashCode() {
return value.GetHashCode();
  }

  // Override operator == and operator != as well;
  //   not necessary, but recommended
}
___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


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

2006-08-23 Thread Generic 2006
On 08/23/2006 04:35 PM, Brian Crowell wrote:
 Generic 2006 wrote:
 I'm facing a strange behavior affecting
 System.Collections.Generic.DictionaryTKey,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.IEquatableTKey), 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.

 IEquatableT is not enough. You need to override Object.GetHashCode()
 and Object.Equals(). IEquatableT is optional, GetHashCode and Equals
 are mandatory.

 --Brian

Thank you Brian for your prompt reply: I've just got an analogous hint
from the guys at IRC #mono.

So I should write something like this (please, let me know):

class Name : IEquatableName
{
 public Name(string value)
 {
  ...
 }

 // Mandatory!!!
 public override int GetHashCode()
 {
  return this.value.GetHashCode();
 }

 // Mandatory!!!
 public override bool Equals(object obj)
 {
  if(obj is Name) return Equals((Name)obj);
  else return false;
 }

 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;}
 }
}

___
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list