Proper way to write GetHashCode() when Equality Comparer is based on OR operation?

可紊 提交于 2019-12-11 07:39:14

问题


I'm trying to write an Equality Comparer for a simple class with 3 fields, like so:

public class NumberClass
{
    public int A { get; set; }
    public int B { get; set; }
    public int C { get; set; }
}

My condition for two objects of NumberClass to be equal is if Obj1.A == Obj2.A || Obj1.B == Obj2.B (in other words, OR), Obj1 and Obj2 being instances of NumberClass.

I can easily write the Equals() of my comparer as follows, but I don't know what to do with my GetHashCode() method.

public bool Equals(NumberClass x, NumberClass y)
{
    if (x.A == y.A || x.B == y.B)
        return true;
    else
        return false;
}

public int GetHashCode(NumberClass obj)
{
    return ???
}

If my condition for equality was AND instead of OR, I could write my GetHashCode() as follows, taken from this SO answer.

public int GetHashCode(NumberClass obj)
{
    unchecked
    {
        int hash = 17;
        if (obj != null)
        {
            hash = hash * 23 + obj.A.GetHashCode();
            hash = hash * 23 + obj.B.GetHashCode();
        }
        return hash;
    }
}

But that obviously wouldn't work for OR since only one of A or B being equal is sufficient for my equality condition to be true.

One workaround I could think of is always returning the same value in GetHashCode() which would be sufficient for LINQ operations such as Distinct(), but I feel like there should be another way as that has its own shortcomings.

What's the proper way to handle this situation?

P.S. For testing, imagine my Main() is the following:

static void Main(string[] args)
{
    List<NumberClass> list = new List<NumberClass>();
    list.Add(new NumberClass { A = 1, B = 2, C = 3 });
    list.Add(new NumberClass { A = 1, B = 22, C = 33 });

    var distinct = list.Distinct(new NumberComparer());
    Console.ReadKey();
}

I expect distinct to contain only the first element in the list.


回答1:


There is no solution for your situation. Your objects violate assumptions that are necessary for an equality comparer to work, for example, it assumes that equality is going to be transitive, but that's not true of your implementation of equality.

You simply won't be able to use any hash-based algorithms so long as you have "fuzzy" equality like that.



来源:https://stackoverflow.com/questions/45601078/proper-way-to-write-gethashcode-when-equality-comparer-is-based-on-or-operatio

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!