1

I have been trying to make my equality definition work but found out that IEqualityComparer does not seem to work whatsoever.

My class:

public class DBTileSimple
{
    public int X;
    public int Y;
    public int Zoom;

    public DBTileSimple(int x, int y, int z)
    {
        X = x;
        Y = y;
        Zoom = z;
    }
}

Testing IEqualityComparer, so it should be equal for any object:

public class TileComparer : IEqualityComparer<DBTileSimple>
{
    public bool Equals(DBTileSimple x, DBTileSimple y)
    {
        return true;
    }

    public int GetHashCode(DBTileSimple obj)
    {
        return 1;
    }
}

Result:

DBTileSimple t1 = new DBTileSimple(10, 20, 17);
DBTileSimple t2 = new DBTileSimple(10, 20, 17);
Log.Info("t1 and t2 = " + (t1 == t2)); 

returns t1 and t2 = false

My ultimate goal is to compare two lists with these objects and do logical operations over them (intersection, etc.).

So for example:

DBTileSimple t1 = new DBTileSimple(10, 20, 17);
DBTileSimple t2 = new DBTileSimple(10, 20, 17);

List<DBTileSimple> list1 = new List<DBTileSimple>();
list1.Add(t1);

List<DBTileSimple> list2 = new List<DBTileSimple>();
list2.Add(t2);

list1 = list1.Except(list2).ToList();

Now list1 should be empty but it is not.

Michal Krča
  • 149
  • 3
  • 15
  • 4
    You aren't using your comparer at all when using `==`. If you want that to work you need to add an overload for `operator ==`. – Lee Sep 01 '17 at 08:53
  • `==` will not call `object.Equals`. Thus you should override it also and let it call `Equals` (or vice versa). – MakePeaceGreatAgain Sep 01 '17 at 08:56
  • == operator doesn't use IEqualityComaprer. You need to override Equals method in DBTitleSimple class. – Chetan Sep 01 '17 at 08:57
  • Possible duplicate of [Operator overloading ==, !=, Equals](https://stackoverflow.com/questions/25461585/operator-overloading-equals) – mjwills Sep 01 '17 at 08:59
  • it also doesn't work when working with lists. List list1 = new List(); list1.Add(t1); List list2 = new List(); list1.Add(t2); list1 = list1.Except(list2).ToList(); list1 should be now empty but is not.. – Michal Krča Sep 01 '17 at 09:02
  • You need to implement `GetHashCode` as well - see the link I provided. – mjwills Sep 01 '17 at 10:04

3 Answers3

6

You don't use the TileComparer at all. If you want to use it to compare to DBTileSimple instances you can do it like that:

DBTileSimple t1 = new DBTileSimple(10, 20, 17);
DBTileSimple t2 = new DBTileSimple(10, 20, 17);
TileComparer comparer = new TileComparer();
Log.Info("t1 and t2 = " + comparer.Equals(t1, t2));

If you want t1 == t2 to work, you have to overload that operator:

public class DBTileSimple
{
    //...

    public static bool operator==(DBTileSimpe t1, DBTileSimpe t2)
    {
        return true;
    }
    public static bool operator!=(DBTileSimpe t1, DBTileSimpe t2)
    {
        return false;
    }
}

Note that you need to overload both == and !=, see Microsoft's guidelines.


UPDATE after your edit:

To use your comparer with Except you simply need to pass an instance of it:

list1 = list1.Except(list2, new TileComparer()).ToList();
René Vogt
  • 43,056
  • 14
  • 77
  • 99
0

You need to implement == operator like this:

public static bool operator ==(DBTileSimple a, DBTileSimple b)
{    
    // Return true if the fields match:
    return a.x == b.x && a.y == b.y && a.Zoom == b.Zoom;
}

public static bool operator !=(DBTileSimple a, DBTileSimple b)
{
    return !(a == b);
}
Jalal
  • 6,594
  • 9
  • 63
  • 100
  • @MichalKrča So as @Rene mentioned in his answer, you need to pass an instance of `TileComparer` to `Except` method. – Jalal Sep 01 '17 at 09:21
0

Overriding the Equals() will have an effect only with

t1.Equals(t2)

To make your code work, you have to add this code in the DBTileSimple class:

public static bool operator ==(DBTileSimple x, DBTileSimple y)
{
    return x.propA == y.propB;
}

Please check this link for more information about overriding equality:

https://msdn.microsoft.com/en-US/library/ms173147(v=vs.80).aspx

EDIT:

If you need to do some other logic besides the equality of two DBTileSimple objects, then I think it would be best to create another method that handles this logic. Equality has to remain as a way of comparing the equality of two objects, otherwise it might cause confusion in the future.