- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我试图了解接口(interface) IEqualityComparer 的 GetHashCode 方法的作用。
以下例子摘自MSDN:
using System;
using System.Collections.Generic;
class Example {
static void Main() {
try {
BoxEqualityComparer boxEqC = new BoxEqualityComparer();
Dictionary<Box, String> boxes = new Dictionary<Box,
string>(boxEqC);
Box redBox = new Box(4, 3, 4);
Box blueBox = new Box(4, 3, 4);
boxes.Add(redBox, "red");
boxes.Add(blueBox, "blue");
Console.WriteLine(redBox.GetHashCode());
Console.WriteLine(blueBox.GetHashCode());
}
catch (ArgumentException argEx) {
Console.WriteLine(argEx.Message);
}
}
}
public class Box {
public Box(int h, int l, int w) {
this.Height = h;
this.Length = l;
this.Width = w;
}
public int Height { get; set; }
public int Length { get; set; }
public int Width { get; set; }
}
class BoxEqualityComparer : IEqualityComparer<Box> {
public bool Equals(Box b1, Box b2) {
if (b1.Height == b2.Height & b1.Length == b2.Length
& b1.Width == b2.Width) {
return true;
}
else {
return false;
}
}
public int GetHashCode(Box bx) {
int hCode = bx.Height ^ bx.Length ^ bx.Width;
return hCode.GetHashCode();
}
}
Equals 方法的实现是否足以比较两个 Box 对象?这就是我们告诉框架用于比较对象的规则的地方。为什么需要 GetHashCode?
谢谢。
卢锡安
最佳答案
先介绍一下背景......
.NET 中的每个对象都有一个 Equals 方法和一个 GetHashCode 方法。
Equals 方法用于将一个对象与另一个对象进行比较 - 查看这两个对象是否相等。
GetHashCode 方法生成对象的 32 位整数表示。由于一个对象可以包含多少信息没有限制,某些散列码由多个对象共享 - 因此散列码不一定是唯一的。
字典是一种非常酷的数据结构,它以更高的内存占用换取(或多或少)添加/删除/获取操作的恒定成本。但是,迭代是一个糟糕的选择。在内部,字典包含一个存储桶数组,其中可以存储值。将键和值添加到字典时,会在键上调用 GetHashCode 方法。返回的哈希码用于确定应存储键/值对的存储桶的索引。
当你想访问Value时,你再次传入Key。在Key上调用GetHashCode方法,定位到包含Value的bucket。
将 IEqualityComparer 传递到字典的构造函数时,将使用 IEqualityComparer.Equals 和 IEqualityComparer.GetHashCode 方法,而不是 Key 对象上的方法。
现在解释为什么这两种方法都是必要的,考虑这个例子:
BoxEqualityComparer boxEqC = new BoxEqualityComparer();
Dictionary<Box, String> boxes = new Dictionary<Box, string>(boxEqC);
Box redBox = new Box(100, 100, 25);
Box blueBox = new Box(1000, 1000, 25);
boxes.Add(redBox, "red");
boxes.Add(blueBox, "blue");
在您的示例中使用 BoxEqualityComparer.GetHashCode 方法,这两个框都具有相同的哈希码 - 100^100^25 = 1000^1000^25 = 25 - 尽管它们显然不是同一个对象。在这种情况下,它们是相同哈希码的原因是因为您使用的是 ^(按位异或)运算符,所以 100^100 抵消掉留下零,1000^1000 也是如此。当两个不同的对象具有相同的键时,我们称之为碰撞。
当我们将具有相同哈希码的两个键/值对添加到字典时,它们都存储在同一个桶中。因此,当我们想要检索一个 Value 时,会在我们的 Key 上调用 GetHashCode 方法来定位桶。由于存储桶中有多个值,字典会遍历存储桶中的所有键/值对,对键调用 Equals 方法以找到正确的值。
在您发布的示例中,两个框是等价的,因此 Equals 方法返回 true。在这种情况下,字典有两个相同的键,因此会抛出异常。
TLDR
所以综上所述,GetHashCode方法就是用来生成一个存放对象的地址的。所以字典不必搜索它。它只是计算哈希码并跳转到该位置。 Equals 方法是一种更好的相等性测试,但不能用于将对象映射到地址空间。
关于c# - GetHashCode 在 .NET 中的 IEqualityComparer<T> 中的作用是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4095395/
'Equal' 和 'GetHashcode' 方法存在于对象类中,我们的类型继承了对象基类。 直接实现对象的两种方法和使用 IComparer 接口(interface)有什么区别? 如果我们覆盖对
在 .NET 中,IEnumerable延伸IEnumerable经常派上用场。令人沮丧的是IEqualityComparer和 IComparer不要扩展它们的非通用对应物,尽管 EqualityC
在我的应用程序的一部分中,我有一个选项可以显示当前艺术家不在音乐库中的专辑列表。为此,我调用音乐 API 来获取该艺术家的所有专辑列表,然后删除当前库中的专辑。 为了应对名称的不同大小写以及标题中丢失
假设我像这样实例化了一个字典 var dictionary = new Dictionary(); MyClass 是我自己的类,它实现了一个 IEqualityComparer<> . 现在,当我
我想为 Nullable 结构编写一个相等比较器。比方说,DateTime? .所以我想出了这段代码: public class NullableEntityComparer : IEqualityC
这是我的测试代码(包含没有在应该返回 true 的时候返回 true): HashSet test = new HashSet(new TilePositionCompare()); test.Add
我有一个不可变的值对象 IPathwayModule,其值定义为: (int) block ; (实体)模块,由(字符串)ModuleId 标识; (枚举)状态;和 (实体)类,由(字符串)Class
我有一个 List存储在我的计算机上的文件路径。我的目的是先过滤掉同名的文件,再过滤掉大小相同的文件。 为此,我创建了两个类来实现 IEqualityComparer , 并实现 Equals和 Ge
我只是想从两个列表中删除重复项并将它们合并到一个列表中。我还需要能够定义什么是重复项。我通过 ColumnIndex 属性定义了一个副本,如果它们相同,则它们是重复的。这是我采用的方法: 我找到了一个
我正在尝试设置一个使用字符串列表作为比较属性的 IEqualityComparer。 在下面的 2 行代码中使用 Except 和 Intersect 时,所有记录都被视为"new",没有一个被识别为
给定两个类 class Contract { public int ID {get; set;} // . . . } class DBContract { public in
我想知道是否有可能在 Distinct 中使用单例作为比较器对象?? 假设我有一个元素列表,我需要在该列表上使用不同的函数。通常我会这样做 var result = list.Distinct(ne
首先我看到IEqualityComparer for anonymous type那里的答案没有回答我的问题,很明显我需要一个 IEqualityComparer不和IComparer用于 Linq
我想从列表中获取不同的对象。我尝试实现 IEqualityComparer 但没有成功。请查看我的代码并给我一个关于 IEqualityComparer 的解释。 public class Messa
我的数据库中有一些相同编号的铃铛。我想得到所有这些而不重复。我创建了一个比较类来完成这项工作,但是该函数的执行导致没有 distinct 的函数出现很大的延迟,从 0.6 秒到 3.2 秒! 我做得对
我正在做一些需要自定义比较器的 LINQ,所以我创建了一个实现 IEqualityComparer 的新类.但是,当我使用它时,我每次都必须创建它的一个实例。 Dim oldListOnly = ol
IEqualityComparer 是否公开,其行为与相等 (=) 运算符相同? LanguagePrimitives 模块包含几个:FastGenericEqualityComparer、Gener
我正在努力实现以下目标: 我有一个表单,用户必须输入姓名、姓氏、地址……以及保存更改按钮。 我想让用户点击保存更改 仅当他确实进行了任何更改时才按下按钮。我发现通过简单地使用 IChangeTrack
我有一个自定义对象列表,我试图在其中删除重复记录。我看到很多在线文章都指向 IEqualityComparer(我以前从未使用过它)。 问题是,我应该什么时候使用它?我可以通过 LINQ 在一行代码中
我想要一个 IEqualityComparer当且仅当两个泛型类型相同且忽略泛型参数时返回 true。所以comparer.Equals(typeof(List), typeof(List))应该返回
我是一名优秀的程序员,十分优秀!