简体   繁体   中英

Custom Class as key for Dictionary in C# not working

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.

You have a problem with equality design . Each equality correspondence must follow these rules:

  1. A.Equals(A) == true for all A .
  2. if A.Equals(B) == true then B.Equals(A) == true for all A, B .
  3. if A.Equals(B) && B.Equals(C) == true then A.Equals(C) == true for all A, 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 .

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 ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM