Comparing object used as Key in Dictionary

Saint picture Saint · Jul 19, 2012 · Viewed 44.1k times · Source

my class:

public class myClass
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
    public int D { get; set; }
}

and main example:

Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>();
myClass first = new myClass();
first.A = 2;
first.B = 3;

myClass second = new myClass();
second.A = 2;
second.B = 3;
second.C = 5;
second.D = 6;

dict.Add(first, new List<string>());

if (dict.ContainsKey(second))
{
    //
    //should come here and update List<string> for first (and only in this example) key 
    //
}
else
{
    //
    //if myFirst object has difference vlues of A or B properties
    //
    dict.Add(second, new List<string>());
}

How to do this?

Answer

Scott Chamberlain picture Scott Chamberlain · Jul 19, 2012

If you always want the dictionary only to compare on A and B, you have two options. Either use the constructor that implements IEqualityComparer<TKey> and put your comparison logic there, or have your class implement IEquateable<T> GetHashCode and Equals so the default comparer will give you the results you are looking for.

If you only want to compare on A and B in your one situation you will need to use the .Keys property and the Linq extension method Contains that allows you to pass in a IEqualityComparer<T>. However, when doing it this way you loose the speed benefits of using a Dictionary, so use it sparingly.

public class MyClassSpecialComparer : IEqualityComparer<myClass>
{
    public bool Equals (myClass x, myClass y)
    { 
        return x.A == y.A && x.B == y.B 
    }

    public int GetHashCode(myClass x)
    {
       return x.A.GetHashCode() + x.B.GetHashCode();
    }


}


 //Special case for when you only want it to compare this one time
 //NOTE: This will be much slower than a normal lookup.
    var myClassSpecialComparer = new MyClassSpecialComparer();
    Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>();
    //(Snip)
    if (dict.Keys.Contains(second, myClassSpecialComparer ))
    {
        //
        //should come here and update List<string> for first (and only in this example) key 
        //
    }

 //If you want it to always compare
    Dictionary<myClass, List<string>> dict = new Dictionary<myClass, List<string>>(new MyClassSpecialComparer());