什么是对GetHash code在的IEqualityComparer&LT的作用; T>在.NET?作用、IEqualityComparer、GetHash、code

2023-09-02 20:43:32 作者:繁华殆尽丶落下一地悲伤

我想了解的接口GetHash code方法的IEqualityComparer。

I'm trying to understand the role of the GetHashCode method of the interface IEqualityComparer.

下面的例子是从MSDN:

The following example is taken from 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方法实现足够比较两个框对象?这就是我们讲的框架,用来比较对象的规则。为什么GetHash code需要?

Shouldn't the Equals method implementation be enough to compare two Box objects? That is where we tell the framework the rule used to compare the objects. Why is the GetHashCode needed?

感谢。

卢西恩

推荐答案

一点背景第一...

在.NET中的每个对象都有一个equals方法和GetHash code方法。

Every object in .NET has an Equals method and a GetHashCode method.

Equals方法用于将一个对象与另一个对象比较 - 。看到如果两个对象是等效

The Equals method is used to compare one object with another object - to see if the two objects are equivalent.

在GetHash code方法生成一个32位整数重新对象presentation。由于没有限制多少信息的一个对象可包含,某些散列codeS是由多个对象共享 - 这样的哈希code是不一定是唯一的。

The GetHashCode method generates a 32-bit integer representation of the object. Since there is no limit to how much information an object can contain, certain hash codes are shared by multiple objects - so the hash code is not necessarily unique.

词典是一个很酷的数据结构,交易更高的内存占用,以换取(或多或少)不变成本添加/删除/获取操作。这是迭代虽然一个糟糕的选择。在内部,一字典包含水桶,其中值可以存储阵列。当您添加键和值到字典中,GetHash code方法被调用的关键。散列code返回的被用来确定在该键/值对应存储桶的索引

A dictionary is a really cool data structure that trades a higher memory footprint in return for (more or less) constant costs for Add/Remove/Get operations. It is a poor choice for iterating over though. Internally, a dictionary contains an array of buckets, where values can be stored. When you add a Key and Value to a dictionary, the GetHashCode method is called on the Key. The hashcode returned is used to determine the index of the bucket in which the Key/Value pair should be stored.

当您要访问的值,你传递的关键了。该GetHash code方法被调用的关键,并包含该值的桶的位置。

When you want to access the Value, you pass in the Key again. The GetHashCode method is called on the Key, and the bucket containing the Value is located.

当一个的IEqualityComparer传递到字典的构造函数中,IEqualityComparer.Equals和IEqualityComparer.GetHash code方法来代替对重点对象的方法。

When an IEqualityComparer is passed into the constructor of a dictionary, the IEqualityComparer.Equals and IEqualityComparer.GetHashCode methods are used instead of the methods on the Key objects.

现在解释为什么这两种方法是必要的,考虑这个例子:

Now to explain why both methods are necessary, consider this example:

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.GetHash code方法,这两个箱子具有相同的哈希code - 100 ^ 100 ^ 25 = 1000 ^ 1000年^ 25 = 25 - 即使它们显然不是相同的对象。他们是相同的哈希code在这种情况的原因是因为您正在使用的^(按位异或)运算符所以100 ^ 100抵消了零留下一样,1000年^ 1000当两个不同的对象具有相同的密钥,我们称之为冲突。

Using the BoxEqualityComparer.GetHashCode method in your example, both of these boxes have the same hashcode - 100^100^25 = 1000^1000^25 = 25 - even though they are clearly not the same object. The reason that they are the same hashcode in this case is because you are using the ^ (bitwise exclusive-OR) operator so 100^100 cancels out leaving zero, as does 1000^1000. When two different objects have the same key, we call that a collision.

当我们使用相同的散列code添加两个键/值对的字典,它们都存储在同一个桶。所以,当我们想获取一个值,该GetHash code方法被称为我们的主要定位桶。由于在桶多个值,对所有在斗呼吁键equals方法键/值对的字典迭代找到正确的。

When we add two Key/Value pairs with the same hashcode to a dictionary, they are both stored in the same bucket. So when we want to retrieve a Value, the GetHashCode method is called on our Key to locate the bucket. Since there is more than one value in the bucket, the dictionary iterates over all of the Key/Value pairs in the bucket calling the Equals method on the Keys to find the correct one.

在您张贴的例子中,两个盒子是等价的,所以Equals方法返回true。在这种情况下,词典有两个相同的密钥,所以它抛出一个异常。

In the example that you posted, the two boxes are equivalent, so the Equals method returns true. In this case the dictionary has two identical Keys, so it throws an exception.

TLDR

因此​​,在总结中,GetHash code方法用于生成该对象被存储的地址。所以一个字典不必搜索它。它只是计算哈希值code和跳转到该位置。 Equals方法是一种较好的测试平等的,但不能用于将对象映射到一个地址空间

So in summary, the GetHashCode method is used to generate an address where the object is stored. So a dictionary doesn't have to search for it. It just computes the hashcode and jumps to that location. The Equals method is a better test of equality, but cannot be used to map an object into an address space.

希望帮助