.net 为什么iQualityComparer<;T>;需要GetHashCode吗?

.net 为什么iQualityComparer<;T>;需要GetHashCode吗?,.net,.net,我知道以前有人问过关于这个问题的各种说法,但我还没有找到任何具体解决我所问问题的方法 在.NET中,我们有IEqualityComparer,它具有以下功能: public interface IEqualityComparer<T> { public bool Equals(T x, T y); public int GetHashCode(T obj); } 公共接口IEqualityComparer { 公共布尔等于(tx,ty); 公共int GetHash

我知道以前有人问过关于这个问题的各种说法,但我还没有找到任何具体解决我所问问题的方法

在.NET中,我们有
IEqualityComparer
,它具有以下功能:

public interface IEqualityComparer<T>
{
    public bool Equals(T x, T y);
    public int GetHashCode(T obj);
}
公共接口IEqualityComparer
{
公共布尔等于(tx,ty);
公共int GetHashCode(T obj);
}
因此,我的问题是,为什么不将其分成两个接口,大致如下:

public interface IEqualityComparer<T>
{
    public bool Equals(T x, T y);
}

public interface IHashProvider<T> : IEqualityComparer<T>
{
    public int GetHashCode(T obj);
}
公共接口IEqualityComparer
{
公共布尔等于(tx,ty);
}
公共接口IHashProvider:IEqualityComparer
{
公共int GetHashCode(T obj);
}
换句话说,我可以理解为什么在任何情况下,如果要对对象执行
GetHashCode
,几乎肯定也需要知道如何执行
Equals
。另外,
Equals
的定义是正确实现
GetHashCode
的一个要求的一部分(如果两个对象相等,它们的哈希代码也必须相等)

然而,从另一个角度看,这似乎不是真的。不难想象这样的情况:您关心通过
Equals
的某个自定义实现检查两个对象是否相等,但不执行任何涉及哈希代码的操作


是否有任何原因导致该接口没有像上述那样被拆分,从而允许方法需要
IHashProvider
(或任何调用)或
IEqualityComparer
,这取决于它们是否会使用哈希代码?这仅仅是一个历史性的决定,现在要改变会太麻烦吗?还是有什么原因让我忽略了始终在
Equals
旁边实现
GetHashCode
很重要?

原因是不值得添加两个单独的接口而不是一个。我强烈建议你阅读Eric Gunnerson写的一篇名为“”的文章,其中介绍了为C#添加功能的成本。归根结底,将
GetHashCode()
Equals()
分离并没有得到足够的证据证明它是独立的接口

我还建议您阅读一些类似主题的文章


    • 原因是不值得添加两个单独的接口而不是一个。我强烈建议你阅读Eric Gunnerson写的一篇名为“”的文章,其中介绍了为C#添加功能的成本。归根结底,将
      GetHashCode()
      Equals()
      分离并没有得到足够的证据证明它是独立的接口

      我还建议您阅读一些类似主题的文章


      IEqualityComparer
      添加到.NET framework的原因是,当您无法使用不同的
      Equals
      /
      GetHashCode
      重写来修改类时(例如,它在其他人的库中),您可以自定义基于哈希的容器的逻辑或者,您不希望出于任何其他原因更改默认实现—例如,为了向后兼容性。这是使用此接口的主要目的:将其提供给散列容器,它们使用它而不是对象附带的
      Equals
      /
      GetHashCode
      逻辑

      平台设计者似乎没有自定义散列容器之外的
      IEqualityComparer
      接口的用例。如果没有
      GetHashCode
      ,外部提供的
      Equals
      本身是有用的,那么很难想出一个场景。NET平台已经为需要通过
      谓词
      外部化双变量(或N变量)检查的用户提供了一种简洁的机制,因此,如果您想编写从外部获取等式检查器的代码,可以执行以下操作:

      void MyFunction(IEnumerable<T> one, IEnumerable<T> two, Predicate<T,T> equalityCheker) {
          foreach (var a in one) {
              foreach (var b in two) {
                  if (equalityCheker(a, b)) {
                      Console.WriteLine("Equal: {0} {1}", a, b);
                  }
              }
          }
      }
      
      void MyFunction(IEnumerable one,IEnumerable two,谓词equalityCheker){
      foreach(var a合一){
      foreach(两个变量b){
      if(均衡切克(a,b)){
      WriteLine(“等于:{0}{1}”,a,b);
      }
      }
      }
      }
      
      IEqualityComparer
      添加到.NET framework的原因是,当您无法使用不同的
      Equals
      /
      GetHashCode
      重写来修改类时(例如,它在其他人的库中),您可以自定义基于哈希的容器的逻辑或者,您不希望出于任何其他原因更改默认实现—例如,为了向后兼容性。这是使用此接口的主要目的:将其提供给散列容器,它们使用它而不是对象附带的
      Equals
      /
      GetHashCode
      逻辑

      平台设计者似乎没有自定义散列容器之外的
      IEqualityComparer
      接口的用例。如果没有
      GetHashCode
      ,外部提供的
      Equals
      本身是有用的,那么很难想出一个场景。NET平台已经为需要通过
      谓词
      外部化双变量(或N变量)检查的用户提供了一种简洁的机制,因此,如果您想编写从外部获取等式检查器的代码,可以执行以下操作:

      void MyFunction(IEnumerable<T> one, IEnumerable<T> two, Predicate<T,T> equalityCheker) {
          foreach (var a in one) {
              foreach (var b in two) {
                  if (equalityCheker(a, b)) {
                      Console.WriteLine("Equal: {0} {1}", a, b);
                  }
              }
          }
      }
      
      void MyFunction(IEnumerable one,IEnumerable two,谓词equalityCheker){
      foreach(var a合一){
      foreach(两个变量b){
      if(均衡切克(a,b)){
      WriteLine(“等于:{0}{1}”,a,b);
      }
      }
      }
      }
      
      如果要比较两个不可变的对象是否相等,则首先检查它们是否具有相同的哈希代码可能会更快。-由于对象是不可变的,所以它们的哈希代码是常量,因此