通过Equals或HashCode进行比较。哪个更快?

时间:2016-03-08 11:28:21

标签: c# performance comparison

我必须将对象与同一个类的原始属性进行比较。 意思是,我必须比较那些:

struct Identifier
{
    string name;
    string email;
}

使用两个字符串名称和电子邮件。 我知道我可以为名称和电子邮件创建一个新的Identifier实例,并将其传递给equals()。我的申请必须非常快速且节省资源。

我知道通过哈希码进行比较并不是一个好方法,因为正如here所解释的那样,存在冲突。但碰撞对我来说没问题,我只需要快速。

所以,

1)通过GetHashCode进行比较(检查两个对象的哈希码是否相同)比Equals()更快?

2)我是否应该为比较创建两个值的标识符的新实例,创建一个直接获取值的新方法? e.g。

struct Identifier {
  string name;
  string email;

  bool Equals(string name, string email) {
      // todo comparison via hashcode or equals
  }
}

I would use the Equals() and GetHashCode() method generated by resharper.

2 个答案:

答案 0 :(得分:6)

如果将哈希代码保存在Identifier实例上,则比较哈希代码会更快(见下文)。但是,与平等比较并不是一回事。

比较哈希码可以让你检查两个项目是否彼此相等:当你得到不同的哈希码时,你知道这一点。

但是,当哈希码相等时,您无法对相等性做出明确的陈述:项目可以相等或不相等。这就是为什么基于散列的容器必须始终遵循哈希代码比较,直接或间接,并进行相等性比较。

尝试按照以下方式实施比较:

struct Identifier {
    string name;
    string email;
    int nameHash;
    int emailHash;
    public Identifier(string name, string email) {
        this.name = name;
        nameHash = name.GetHashCode();
        this.email = email;
        emailHash = email.GetHashCode();
    }
    bool Equals(string name, string email) {
        return name.GetHashCode() == nameHash
            && email.GetHashCode() == emailHash
            && name.equals(this.name)
            && email.equals(this.email);
    }
}

与预先计算的哈希代码相比,会使实际的相等比较短路,因此当大多数比较最终返回false时,您可以节省一些CPU周期。

答案 1 :(得分:5)

  

是通过GetHashCode进行比较(检查两个对象的哈希码   是相同的)比Equals()更快?

你似乎混淆了这两个概念。 GetHashCode的目的不是寻求两个对象实例之间的相等,它就是这样,每个对象都可以轻松地为任何外部资源提供哈希码值。继续它。

另一方面,

Equals是确定平等的。应该是两个为equals生成true的方法,提供相同的哈希码,但不是相反。

The documentation on object.GetHashCode提供了一个非常好的解释:

  

两个相等的对象返回相等的哈希码。然而,   相反的情况并非如此:相等的哈希码并不意味着对象   相等,因为不同(不相等)的对象可以具有相同的哈希值   码。此外,.NET Framework不保证默认值   执行GetHashCode方法,以及此方法的值   .NET Framework版本和平台之间的返回可能不同,例如   作为32位和64位平台。由于这些原因,请不要使用   此方法的默认实现作为唯一对象标识符   用于散列目的。由此产生两种结果:

     
      
  • 您不应该假设相等的哈希码意味着对象相等。
  •   
  • 您永远不应该在应用程序域之外持久存储或使用哈希代码   它是创建它的,因为同一个对象可以散列   应用程序域,进程和平台。
  •   

如果您想检查两个实例之间的相等性,我绝对建议您实施IEquatable<T>并覆盖object.GetHashCode

作为旁注 - 我发现您正在使用struct。你应该注意到struct在C#中的语义与在C ++或C中的语义不同,我希望你能够意识到它们。