为什么不在我定义IEqualityComparer <t> </t>时除外

时间:2013-09-30 16:13:51

标签: c# linq

如果我尝试这样做 - 我对oldList.Except(newList)的调用似乎返回所有项目 - 没有比较工作。

   List<ControlAndTopLevelControlPair> oldOnly = oldList.Except( newList ).ToList();

   public class ControlAndTopLevelControlPair : IEqualityComparer<ControlAndTopLevelControlPair>
   {
      public int CONTROLOI { get; set; }
      public int VIEWCONTROL_OI { get; set; }
      public bool Equals( ControlAndTopLevelControlPair x, ControlAndTopLevelControlPair y )
      {
         return x.CONTROLOI.Equals( y.CONTROLOI ) && x.VIEWCONTROL_OI.Equals( y.VIEWCONTROL_OI );
      }

      public int GetHashCode( ControlAndTopLevelControlPair obj )
      {
         return obj.CONTROLOI.GetHashCode( ) ^ obj.VIEWCONTROL_OI.GetHashCode( );
      }

但是,如果我定义一个自定义比较器,那么以下工作:

List<ControlAndTopLevelControlPair> oldOnly = oldList.Except( newList, new ControlAndTopLevelControlPairComparer() ).ToList( );

   public class ControlAndTopLevelControlPairComparer : IEqualityComparer<ControlAndTopLevelControlPair>
   {
      public bool Equals( ControlAndTopLevelControlPair x, ControlAndTopLevelControlPair y )
      {
         return x.CONTROLOI.Equals( y.CONTROLOI ) && x.VIEWCONTROL_OI.Equals( y.VIEWCONTROL_OI );
      }

      public int GetHashCode( ControlAndTopLevelControlPair obj )
      {
         return obj.CONTROLOI.GetHashCode() ^ obj.VIEWCONTROL_OI.GetHashCode();
      }
   }

3 个答案:

答案 0 :(得分:2)

当您未指定Comparer时,它将默认调用您未实现的GetHashCodeEquals(object)

如果你在方法中放置一个断点,你会发现它们从未被调用过。如果您对GetHashCode()Equals(object)的实施执行相同的操作,则会看到 被调用。

public class ControlAndTopLevelControlPair 
{
  public int CONTROLOI { get; set; }
  public int VIEWCONTROL_OI { get; set; }

  public override int GetHashCode() {  return CONTROLOI ^ VIEWCONTROL_OI; }
  public override bool Equals (object other) 
  {
     // your implementation
  }
}

答案 1 :(得分:2)

IEqualityComparer是您定义一个对象的接口,该对象的唯一任务是比较其他一些对象

使用IEquatable对象定义对象如何比较本身与另一个对象的相等性。如果你这样做,那么你不需要创建一个新的比较器对象并将其传递给Except

确保在实施IEquatble时,您也可以覆盖对象的GetHashCode方法。

public class ControlAndTopLevelControlPair : IEquatable<ControlAndTopLevelControlPair>
{
    public int CONTROLOI { get; set; }
    public int VIEWCONTROL_OI { get; set; }
    public bool Equals(ControlAndTopLevelControlPair other)
    {
        if (other == null) return false;
        return CONTROLOI.Equals(other.CONTROLOI)
            && VIEWCONTROL_OI.Equals(other.VIEWCONTROL_OI);
    }
    public override bool Equals(object obj)
    {
        return Equals(obj as ControlAndTopLevelControlPair);
    }
    public override int GetHashCode()
    {
        return CONTROLOI.GetHashCode() ^ VIEWCONTROL_OI.GetHashCode();
    }
}

如果你要覆盖GetHashCode,你还应该覆盖对象的Equals方法,以便两个相等的定义保持同步。

答案 2 :(得分:1)

在第一种情况下,您需要override EqualsGetHashCode

public class ControlAndTopLevelControlPair {
  public int CONTROLOI { get; set; }
  public int VIEWCONTROL_OI { get; set; }
  public override bool Equals(object x)
  {
     ControlAndTopLevelControlPair c = x as ControlAndTopLevelControlPair;
     if(c == null) return false;
     return c.CONTROLOI.Equals(CONTROLOI) && c.VIEWCONTROL_OI.Equals(VIEWCONTROL_OI);
  }

  public override int GetHashCode()
  {
     return CONTROLOI.GetHashCode( ) ^ VIEWCONTROL_OI.GetHashCode( );
  }
}

请注意override个关键字,该类不需要实现IEqualityComparer