I recently started studying C# but am stuck on this particular case. Yes I have gone over the previous questions but was not able to get what the issue in my code is. Custom Class used as key in Dictionary but key not found This is the closest one I could find, but the answer given here does not seem to work for me.
I have a Dictionary registry<Customers, string>. Customers is a class that has 2 strings: s1 and s2. A customer can match either s1 or s2 (both are not required).
Class Customers:
public class Customers
{
public string _s1;
public string _s2;
public Customers(string s1, string s2)
{
_s1 = s1;
_s2 = s2;
}
public class EqualityComparer : IEqualityComparer<Customers>
{
public bool Equals(Customers x, Customers y)
{
Console.WriteLine("Inside Equals");
return ((x._s1.Equals(y._s1)) || (x._s2.Equals(y._s2)));
}
public int GetHashCode(Customers x)
{
return x._s1.GetHashCode() ^ x._s2.GetHashCode();
}
}
}
Program.cs:
Dictionary<Customers, string> registry = new Dictionary<Customers, string>(new Customers.EqualityComparer());
Customers key = new Customers("1", "2");
Customers key2 = new Customers("12", "21");
registry.Add(key, "12");
registry.Add(key2, "22");
Customers lookUp1 = new Customers("1", "2");
Customers lookUp2 = new Customers("1", "32");
if (registry.ContainsKey(lookUp2))
{
Console.WriteLine("Found");
}
else
{
Console.WriteLine("Not Found");
}
The issue is that when both s1 and s2 are matching, then I get "Found", but when only one of them does I get "Not found" despite having changed Equals() accordingly and giving the reference of the new EqualityComparer in the Constructor as well.
Also, For lookup1 I do get "Inside Equals" but not for lookup2 and I'm not sure why.
CodePudding user response:
You have a problem with equality design. Each equality correspondence must follow these rules:
A.Equals(A) == true
for allA
.- if
A.Equals(B) == true
thenB.Equals(A) == true
for allA, B
. - if
A.Equals(B) && B.Equals(C) == true
thenA.Equals(C) == true
for allA, B, C
.
As we can see, the rule #3 (transitive rule) is broken:
Customer A = new Customer("x", "y");
Customer B = new Customer("x", "z");
Customer C = new Customer("p", "z");
Since equality is implemented incorrectly, Dictionary<K, V>
doesn't work properly.
CodePudding user response:
This happens because Dictionary
is basically a hash table:
Retrieving a value by using its key is very fast, close to O(1), because the
Dictionary<TKey,TValue>
class is implemented as a hash table.
and first rule for matching is that hashcodes should be equal and "1".GetHashCode() ^ "2".GetHashCode()
(for key
) will definitely differ from "1".GetHashCode() ^ "32".GetHashCode()
(for lookUp2
).