【问题标题】:IEqualityComparer not working at allIEqualityComparer 根本不工作
【发布时间】:2018-02-10 07:08:27
【问题描述】:

我一直在尝试使我的相等定义起作用,但发现 IEqualityComparer 似乎不起作用。

我的班级:

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

测试 IEqualityComparer,所以它应该对任何对象都相等:

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

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

结果:

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

返回 t1 和 t2 = false

我的最终目标是将两个列表与这些对象进行比较并对它们进行逻辑运算(交集等)。

例如:

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();

现在 list1 应该是空的,但它不是。

【问题讨论】:

  • 您在使用== 时根本没有使用您的比较器。如果你想让它工作,你需要为 operator == 添加一个重载。
  • == 不会调用object.Equals。因此,您也应该覆盖它并让它调用Equals(反之亦然)。
  • == 运算符不使用 IEqualityComaprer。您需要重写 DBTitleSimple 类中的 Equals 方法。
  • 它在处理列表时也不起作用。列表 list1 = 新列表(); list1.Add(t1);列表 list2 = 新列表(); list1.Add(t2); list1 = list1.Except(list2).ToList(); list1 现在应该是空的,但不是..

标签: c# object compare


【解决方案1】:

你根本不使用TileComparer。如果你想用它来比较 DBTileSimple 实例,你可以这样做:

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

如果你想让t1 == t2 工作,你必须重载那个操作符:

public class DBTileSimple
{
    //...

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

请注意,您需要同时重载==!=,请参阅Microsoft's guidelines


修改后更新:

要将您的比较器与Except 一起使用,您只需传递它的一个实例:

list1 = list1.Except(list2, new TileComparer()).ToList();

【讨论】:

    【解决方案2】:

    重写 Equals() 仅对

    有效
    t1.Equals(t2)
    

    要使您的代码正常工作,您必须在 DBTileSimple 类中添加此代码:

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

    请查看此链接以获取有关覆盖平等的更多信息:

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

    编辑:

    如果除了两个 DBTileSimple 对象的相等性之外,您还需要执行一些其他逻辑,那么我认为最好创建另一个处理此逻辑的方法。必须保留相等性作为比较两个对象相等性的一种方式,否则将来可能会引起混乱。

    【讨论】:

      【解决方案3】:

      您需要像这样实现 == 运算符:

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

      【讨论】:

      • @MichalKrča 正如@Rene 在他的回答中提到的那样,您需要将TileComparer 的实例传递给Except 方法。
      猜你喜欢
      • 1970-01-01
      • 2016-10-29
      • 2017-03-19
      • 2013-09-20
      • 2013-11-08
      • 2015-08-23
      • 2017-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多