Question

I'm trying to compare custom type in two List<T> and use the Intersect / Except method. The equality is determined by three fields of this type. The equality is based on more than the ordinary condition (all fields contains the same data). I implemented of course the IEqualityComparer<T>. My problem is that the GetHashCode() method return not equal once the hashCode is not the same and this does not help me since this is not true in my case.

Is there any way to compare two custom object when equality is based on more than one condition so I can use intersect/except/distinct etc...?

Here is my code :

public bool Equals(ComparableObject x, ComparableObject y)
{
    if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
        return false;

    if (Object.ReferenceEquals(x, y))
        return true;

    if (x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return true;


    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return true;

    if (x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && x.Var2.Equals(y.Var2))
        return false;

    if (!x.Var1.Equals(y.Var1) && !x.Var3.Equals(y.Var3) && !x.Var2.Equals(y.Var2))
        return false;


    return x.Var1.Equals(y.Var1) && x.Var1.Equals(y.Var1) && x.Var3.Equals(y.Var3);
}


public int GetHashCode(ComparableObject x)
{
    return obj.Var1.GetHashCode() ^ obj.Var2.GetHashCode()^ obj.Var3.GetHashCode()
}
Was it helpful?

Solution

It is your job to provide such GetHashCode() that the value it returns will be different for objects that are different (in as many cases as possible; you still may return same hash code for non-equal objects), and will always be same for objects that may be equal (in all cases; you may not return different hash code for equal objects).

For instance, if one of the three fields you compare is an int, you can return that field as GetHashCode().

If, however, it's difficult to come up with something clever, you can return a constant, such as 42. This way Equals() will be called for all object pairs, delivering expected results, although in the least performant way.

OTHER TIPS

Not sure if you have other problems with GetHashCode in your underlying types, but this is an example of a custom type and an IEqualityComparer that returns true if only the first two fields are the same. This will allow Except etc. to work on the type.

    public class CustomType
    {
        public int Val1 { get; set; }
        public int Val2 { get; set; }
        public int Val3 { get; set; }
    }

    class CustomTypeComparer : IEqualityComparer<CustomType>
    {
        public bool Equals(CustomType x, CustomType y)
        { return x.Val1 == y.Val1 && x.Val2 == y.Val2; }

        public int GetHashCode(CustomType obj)
        { return obj.Val1.GetHashCode() ^ obj.Val2.GetHashCode(); }
    }

If your properties are not simple types as int, you may want to use Equals() instead of == to compare the objects.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top