繁体   English   中英

IEquatable 中的条件<t> 。等于</t>

[英]Condition in IEquatable<T>.Equals

我已经实现IEquatable<T>来比较两个列表中的对象,但是我想有条件地这样做:

public bool Equals(CustomerType other)
{

    if (this.Zipcode == "11111" || this.Zipcode == "22222" || this.Zipcode== "33333")
       {
          return this.FirstName.Equals(other.FirstName) && this.LastName.Equals(other.LastName) && this.MiddleName.Equals(other.MiddleName);
       }
       else
       {
          return this.FirstName.Equals(other.FirstName);
       }
}

这里出了点问题,它永远不会进入其他条件。 有人可以告诉我我哪里出错了吗?

- 用法 -

var v = listA.Except(listB).ToList();

--GetHashCode 实现--

    public override int GetHashCode()
    {
        unchecked
        {

            int hash = 17;         
            hash = hash * 23 + this.intField1.GetHashCode();         
            hash = hash * 23 + this.intField2.GetHashCode();         
            hash = hash * 23 + this.stringField3.GetHashCode();
            hash = hash * 23 + this.doubleField4.GetHashCode();
            hash = hash * 23 + this.doubleField5.GetHashCode();         

            return hash;
        }
    }

- 等于 -

    public override bool Equals(object obj) 
    {
        if (obj == null) return base.Equals(obj);
        if (obj is CustomerType ) 
        { 
            return this.Equals((CustomerType)obj); 
        } 
        else 
        { 
            return false; 
        } 
    }

- 例子 -

ListA 有 2 个客户:

Cust1:名字 - “A” 姓氏 - “Z” 中间名 - “Y” 邮政编码 - “11111”

Cust2:名字-“B”姓氏-“X”中间名-“W”邮政编码-“44444”

ListB 有 2 个客户:

Cust1:名字 - “A” 姓氏 - “Z” 中间名 - “Y” 邮政编码 - “11111”

Cust2:名字-“B”姓氏-“G”中间名-“G”邮政编码-“44444”

在这里,当我说 ListA.Except(ListB) 时,它会将 CustA 与 FirstName、MiddleName、LastName 进行比较,因为它属于 Zipcode 11111 和只有 FirstName 的 CustB,当我说 ListB.Except(ListA) 时也是如此。 当前 Equals 实现中发生的事情是它与 ListA.Except(ListB) 一起工作得很好,但是当我说 ListB.Except(ListA) 时,它会比较 CustB 的 FirstName、LastName 和 Middlename。

我很确定您没有正确实现GetHashCode() 每当您覆盖Equals时,您必须覆盖GetHashCode()以使它们保持一致。

条件是,如果对于两个对象o1.Equals(o2)返回 true,则GetHashCode的结果必须相同。

由于Except在内部使用哈希集,因此GetHashCode()的实现在这里是相关的。 如果没有哈希集,它的复杂性将从 O(n) 增加到 O(n^2),这显然是不可取的。

除此之外, Equals应该是对称的,而你的不是。


查看您的GetHashCode() function 显然是错误的。 它考虑了Equals没有考虑的字段。

每当您的代码进入ifthen部分时,它可能会考虑FirstNameLastNameMiddleName 当您的代码进入else部分时,它可能只考虑GetHashCode()FirstName

public override int GetHashCode()
{
    unchecked
    {
    if (this.Zipcode == "11111" || this.Zipcode == "22222" || this.Zipcode== "33333")
    {
        return FirstName.GetHashCode()*529+
               LastName.GetHashCode()*23+
               MiddleName.GetHashCode();
    }
    else
    {
        return FirstName.GetHashCode();
    }
}

但是即使使用GetHashCode()的这种实现,您仍然应该修复Equals的对称性

关于您的 equals 和 hashcode 函数的对称性,并根据您在另一个答案的评论中所说的话,我相信这是您需要的实现:

public bool Equals(CustomerType other)
{

    if ((this.Zipcode == "11111" || this.Zipcode == "22222" || this.Zipcode== "33333") &&
        (other.Zipcode == "11111" || other.Zipcode == "22222" || other.Zipcode== "33333"))
       {
          return this.FirstName.Equals(other.FirstName) && 
                 this.LastName.Equals(other.LastName) && 
                 this.MiddleName.Equals(other.MiddleName);
       }
       else
       {
          return this.FirstName.Equals(other.FirstName);
       }
}

对于 GetHashCode:

public override int GetHashCode()
{
    if (this.Zipcode == "11111" || this.Zipcode == "22222" || this.Zipcode== "33333")
    {
        return FirstName.GetHashCode() ^ LastName.GetHashCode() ^ MiddleName.GetHashCode();
    }
    else
    {
        return FirstName.GetHashCode();
    }
}

ETA - 稍微扩展一下 - 您的实现似乎与平等的定义不符。

做一个稍微不同的假设(客户 B 和 A 的名字相同),问自己以下问题:

  1. 客户 A 等于客户 B 吗? 根据您的代码,答案是否定的。
  2. 客户 B 等于客户 A 吗? 根据您的代码,答案是肯定的。

在比较客户 A 和客户 B 时,您的实现将使用名字、姓氏和中间名。 但是在将客户 B 与客户 A 进行比较时,您的实现将只使用名字。 这违反了平等的基本定义

对称属性指出:

 * For any quantities a and b, if a = b, then b = a.

任何依赖于Equals方法的内置函数都将假定其实现与相等的定义一致。 由于您的实施不是,因此您违反了该假设,因此得到了不一致的结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM