我试着去理解方面的作用GetHashCode方法的接口IEqualityComparer.

下面的例子取自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();
    }
}

不应等的方法实现足够比较两个盒子的对象?这就是我们告诉该框架使用的规则比较的对象。为什么是GetHashCode需要?

谢谢。

卢西恩

有帮助吗?

解决方案

有点背景...

.NET中的每个对象都有一个等效方法和GethashCode方法。

Equals方法用于将一个对象与另一个对象进行比较 - 查看两个对象是否等效。

GethashCode方法生成对象的32位整数表示。由于对象可以包含多少信息没有限制,因此某些哈希代码由多个对象共享 - 因此,哈希代码不一定是唯一的。

词典是一种非常酷的数据结构,可以交易更高的内存足迹,以回报(或多或少)添加/删除/获得操作的恒定成本。迭代的选择是一个糟糕的选择。在内部,字典包含一个存储库,可以存储值。当您在字典中添加键和值时,键在键上调用GethashCode方法。返回的哈希码用于确定应存储键/值对的存储桶的索引。

当您想访问该值时,您会再次通过键。 GethashCode方法在钥匙上调用,并且包含该值的铲斗位于位置。

当iequalityComparer传递到字典的构造函数中时,使用iqualityComparer.Equals和iequalityComparer.gethashcode方法而不是关键对象上的方法。

现在要解释为什么两种方法都是必要的,请考虑以下示例:

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^1000^25 = 25-即使它们显然不是同一对象。在这种情况下它们是相同的哈希码的原因是,您正在使用^(bitwise exclusive-or)operator,因此100^100取消了零,而1000^1000也是如此。当两个不同的对象具有相同的键时,我们称之为碰撞。

当我们在字典中添加两个具有相同哈希码的键/值对时,它们都存储在同一桶中。因此,当我们要检索一个值时,请在我们的键上调用GethashCode方法以找到存储桶。由于存储桶中有多个值,因此字典在键上调用键方法的所有键/值对迭代以找到正确的方法。

在您发布的示例中,两个框是等效的,因此等效方法返回true。在这种情况下,字典具有两个相同的键,因此会引发异常。

tldr

因此,总而言之,GethashCode方法用于生成存储对象的地址。因此,词典不必搜索它。它只是计算哈希码并跳到该位置。平等方法是更好的平等测试,但不能用于将对象映射到地址空间中。

希望有帮助

其他提示

gethashcode 用于词典菌落中,并创建用于存储对象的哈希。这是一篇不错的文章,为什么以及如何使用 iequaltycomparergethashcode http://dotnetperls.com/iequalitycomparer

同时这将可能对一个 Dictionary<TKey,TValue> 要拥有它 GetValue 和类似方法的呼叫 Equals 在每一个储存关键要看它是否相匹配的一个要求,那将是非常缓慢。相反,像许多基于散列的收藏,它依靠 GetHashCode 快速排除最不匹配值,从审议。如果叫 GetHashCode 在一个项目正在寻求产率42、以及收集有53,917项目,但是呼叫 GetHashCode 在53,914的项目取得了值42,那么只有3个项目将有可相比的人被要求。其他53,914可以安全地被忽略。

的原因 GetHashCode 是包含在一个 IEqualityComparer<T> 是允许的可能性一词典的消费者可能需要方面,作为平等对象,通常会 一方面互相平等的。最常见的例子将是一个叫想要使用的字符串钥匙,但使用情况不敏感的比较。为了使这项工作有效率,这本字典将需要有某种形式的散列函数,将产生同样的价值为"福克斯"和"福克斯"的,但希望收率别的东西为"盒子"或"斑马"。由于 GetHashCode 方法建成 String 不工作的方式,该词典将需要得到这样的方法从其他地方, IEqualityComparer<T> 是最合乎逻辑的,因为需要这样的散列码将是非常强烈地相关的一个 Equals 方法,认为"福克斯"和"福克斯"彼此相同,但不要"箱子"或"斑马"。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top