.net 为什么iQualityComparer<;T>;需要GetHashCode吗?
我知道以前有人问过关于这个问题的各种说法,但我还没有找到任何具体解决我所问问题的方法 在.NET中,我们有.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
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);
}
}
}
}
如果要比较两个不可变的对象是否相等,则首先检查它们是否具有相同的哈希代码可能会更快。-由于对象是不可变的,所以它们的哈希代码是常量,因此