Comparing object used as Key in Dictionary

前端 未结 3 929
一向
一向 2020-12-10 11:11

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


        
相关标签:
3条回答
  • 2020-12-10 11:40

    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());
    
    0 讨论(0)
  • 2020-12-10 11:43

    By default, comparison puts objects into buckets based on their hash code. A detailed comparison is then performed (by calling Equals) if two hash codes are the same. If your class neither provides GetHashCode or implements equality, the default object.GetHashCode will be used--in which case nothing specific to your class will be used for value comparison semantics. Only the same reference will be found. If you don't want this, implement GetHashCode and implement equality.

    For example:

    public class myClass
    {
        public int A { get; set; }
        public int B { get; set; }
        public int C { get; set; }
        public int D { get; set; }
    
        public bool Equals(myClass other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.A == A && other.B == B && other.C == C && other.D == D;
        }
    
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (myClass)) return false;
            return Equals((myClass) obj);
        }
    
        public override int GetHashCode()
        {
            unchecked
            {
                int result = A;
                result = (result*397) ^ B;
                result = (result*397) ^ C;
                result = (result*397) ^ D;
                return result;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-10 11:43

    Override in your myClass:

    • GetHashCode method

    • Equals method

    To implement GetHashCode method you can just XOR GetHashCodes from your integer properties.

    Optionally override ToString method and implement IEquatable interface

    0 讨论(0)
提交回复
热议问题