views:

334

answers:

4

I have a class, show below, which is used as a key in a Dictionary<ValuesAandB, string> I'm having issues when trying to find any key within this dictionary, it never finds it at all. As you can see, I have overridden Equals and GetHashCode.

To look for the key I'm using

ValuesAandB key = new ValuesAandB(A,B);
if (DictionaryName.ContainsKey(key)) {
   ...
}

Is there anything else that I'm missing? Can anyone point out what I'm doing wrong?

private class ValuesAandB {
   public string valueA;
   public string valueB;

   // Constructor
   public ValuesAandB (string valueAIn, string valueBIn) {
     valueA = valueAIn;
     valueB = ValueBIn;
   }

   public class EqualityComparer : IEqualityComparer<ValuesAandB> {
      public bool Equals(ValuesAandB x, ValuesAandB y) {
         return ((x.valueA.Equals(y.valueA)) && (x.valueB.Equals(y.valueB)));
      }
      public int GetHashCode(ValuesAandB x) {
         return x.valueA.GetHashCode() ^ x.valueB.GetHashCode();
      }
   }
}

And before anyone asks, yes the values are in the Dictionary!

+1  A: 

You have not overridden Equals and GetHashCode. You have implemented a second class which can serve as an EqualityComparer. If you don't construct the Dictionary with the EqualityComparer, it will not be used.

The simplest fix would be to override GetHashCode and Equals directly rather than implementing a comparer (comparers are generally only interesting when you need to supply multiple different comparison types (case sensitive and case insensitive for example) or when you need to be able to perform comparisons on a class which you don't control.

StarPacker
Yes, comments taken on board and the correct answer as it turned out, but Greg Beech got in ahead of you am afraid.Thanks for the help though.
Ian Devlin
A: 

It looks like you're comparing two strings. Iirc, when using .Equals(), you are comparing the reference of the strings, not the actual contents. To implement an EqualityComparer that works with strings, you would want to use the String.Compare() method.

public class EqualityComparer : IEqualityComparer<ValuesAandB>
{
     public bool Equals(ValuesAandB x, ValuesAandB y)
     {
          return ((String.Compare(x.valueA,y.valueA) == 0) &&
            (String.Compare(x.valueB, y.valueB) == 0));
     }
     // gethashcode stuff here
}

I could be a little off with the code, that should get you close...

cloggins
No, String.Equals(String) is the overload that will be called here, which very explicitly compares the contents. And in any case, String.Equals(Object) is overridden to do the same.
Greg Beech
*facepalm* I'm not sure what I was thinking.
cloggins
A: 

I had this problem, turns out the dictionary was comparing referances for my key, not the values in the object.

I was using a custom Point class as keys. I overrode the ToString() and the GetHashCode() methods and viola, key lookup worked fine.

Muad'Dib
+2  A: 

Token answer as my comment turned out to be correct :-)

How are you constructing the dictionary? Are you passing your custom equality comparer in to its constructor?

Greg Beech
Accepted as promised! Thanks again.
Ian Devlin