c# - 比较两个对象时有条件地更改 GetHashCode()

标签 c# .net performance comparison gethashcode

我有两个不同的对象列表,并希望根据某些属性的权重获得它们的相似性。最快的方法似乎是实现一个 IEquatable 接口(interface),这就是我所做的:

public class CompareEntry : IEquatable<CompareEntry>
{
    public int LeadId { get; set; }
    public int SaleId { get; set; }
    public string Email { get; set; }
    public string PhonePrivate { get; set; }
    public string PhoneMobile { get; set; }
    public string PhoneCompany { get; set; }
    public string FirstName { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
    public string ZipCode { get; set; }
    public string CompanyName { get; set; }

    public bool Equals(CompareEntry other)
    {
        int weight = 0;

        //Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null))
        {
            return false;
        }

        //Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other))
        {
            return true;
        }

        if ((this.CheckProperties(this.Email, other.Email) && this.Email == other.Email)
           || (this.CheckProperties(this.PhonePrivate, other.PhonePrivate) && this.PhonePrivate == other.PhonePrivate)
           || (this.CheckProperties(this.PhoneMobile, other.PhoneMobile) && this.PhoneMobile == other.PhoneMobile)
           || (this.CheckProperties(this.PhoneCompany, other.PhoneCompany) && this.PhoneCompany == other.PhoneCompany))
        {
            weight += 100;
        }

        if ((this.CheckProperties(this.Name, other.Name) && this.Name == other.Name)
            || (this.CheckProperties(this.FirstName, other.FirstName) && this.FirstName == other.FirstName))
        {
            weight += 25;
        }

        if ((this.CheckProperties(this.City, other.City) && this.City == other.City)
            || (this.CheckProperties(this.ZipCode, other.ZipCode) && this.ZipCode == other.ZipCode))
        {
            weight += 12;
        }

        if (this.CheckProperties(this.CompanyName, other.CompanyName) && this.CompanyName == other.CompanyName)
        {
            weight += 5;
        }

        return weight > 50;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = (int)2166136261;

            hash = hash * 16777619 ^ (string.IsNullOrEmpty(Email) ? 0 : Email.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(PhonePrivate) ? 0 : PhonePrivate.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(PhoneMobile) ? 0 : PhoneMobile.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(PhoneCompany) ? 0 : PhoneCompany.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(FirstName) ? 0 : FirstName.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(Name) ? 0 : Name.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(City) ? 0 : City.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(ZipCode) ? 0 : ZipCode.GetHashCode());
            //hash = hash * 16777619 ^ (string.IsNullOrEmpty(CompanyName) ? 0 : CompanyName.GetHashCode());

            return hash;
        }
    }

    private bool CheckProperties(string prop, string otherProp)
    {
        return !string.IsNullOrEmpty(prop) && !string.IsNullOrEmpty(otherProp);
    }
}

问题是,当我覆盖 GetHashCode() 方法时,我只会得到那些完全相同的人,或者在这种特殊情况下 - 只得到相同的电子邮件。

如何在 GetHashCode() 方法中有条件地检查权重,以便我可以使用更正方法 Equals? 或者有没有一种方法可以用其他方式进行相似性检查,哪种方式性能好?

最佳答案

Equals/GetHashCode 并非旨在比较“基本相等”的事物。在这种情况下,相等只是一个 bool 属性。特别是,采用模糊的“基本相等”方法会导致传递性问题。 Object.Equals的文档包括此要求:

If (x.Equals(y) && y.Equals(z)) returns true, then x.Equals(z) returns true.

当你有模糊相等时,这根本不成立。仅仅因为 x “非常像”yy “非常像”z 并不意味着x“非常像”z

现在您可以做的是有一个只比较电话号码的相等比较器,另一个只比较名字的相等比较器,等等——但这不会真正让你模糊匹配。

关于c# - 比较两个对象时有条件地更改 GetHashCode(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30703990/

相关文章:

c# - .net 中的小数百分比符号

c# - 第三方库中麻烦的 GC.collect() 调用

python - Whoosh 有多快?

c# - 服务器上调度程序中的特定场景 : Windows Services vs Azure Job, 控制台应用程序?

c# - VS2010 编译器错误 "is not assignable to parameter type T"我相信不是约束问题

c# - 发布后 MVC3 不重定向

sql-server - 与查询单独运行时相比,查询在跟踪中显示的持续时间值更大

c# - 为什么这个指定的转换无效??

c# - 在 Visual Studio 2013 中运行单元测试时运行其他项目

c# - 此代码的正确 IDisposable 实现