简体   繁体   English

实施IEqualityComparer时 <T> .GetHashCode(T obj),我可以使用当前实例的状态,还是必须使用obj?

[英]When implementing IEqualityComparer<T>.GetHashCode(T obj), can I use the current instance's state, or do I have to use obj?

How come when I implement IEqualityComparer, it has a parameter for GetHashCode(T obj)? 当实现IEqualityComparer时,为什么它具有GetHashCode(T obj)的参数呢? It's not a static object of course, so why can't I just use the current instance's state to generate the hash code? 当然,它不是静态对象,所以为什么不能仅使用当前实例的状态来生成哈希码? Is this == obj ? 这是this == obj吗?

I'm curious because I'm trying to do this: 我很好奇,因为我正在尝试这样做:

public abstract class BaseClass : IEqualityComparer<BaseClass>
{
    public abstract int GetHashCode(BaseClass obj);
}

public class DerivedClass : BaseClass
{
    public int MyData;

    public override int GetHashCode(BaseClass obj)
    {
        return MyData.GetHashCode();
        // Or do I have to do this:
        // return (DerivedClass)obj.MyData.GetHashCode();
    }
}

I'm trying to prevent doing the cast, since it's being used in really high-performance code. 我试图避免进行强制类型转换,因为它已在真正的高性能代码中使用。

I think the main issue here is that you're confusing IEqualityComparer<T> with IEquatable<T> . 我认为这里的主要问题是您将IEqualityComparer<T>IEquatable<T>混淆了。

IEquatable<T> defines a method for determining if the current instance ( this ) is equal to an instance of the same type. IEquatable<T>定义了一种用于确定当前实例( this )是否等于相同类型的实例的方法。 In other words it's used for testing objA.Equals(objB) . 换句话说,它用于测试objA.Equals(objB) When implementing this interface, it is recommended that you also override the GetHashCode() instance method. 在实现此接口时,建议您还重写GetHashCode()实例方法。

IEqualityComparer<T> defines methods for testing whether two objects of the given type are equal, in other words, it's for testing comparer.Equals(objA, objB) . IEqualityComparer<T>定义用于测试给定类型的两个对象是否相等的方法,换句话说,它用于测试comparer.Equals(objA, objB) Hence the necessity to to provide an object as a parameter to GetHashCode (which, remember is different than the GetHashCode that it inherits from object ) 因此,有必要提供一个对象作为GetHashCode的参数(记住,它不同于它从object继承的GetHashCode

You can think of IEquatable<T> as your object's way of saying, " this is how I know if I am equal to something else, " and IEqualityComparer<T> as your object's way of saying, " this is how I know if two other things are equal ". 您可以将IEquatable<T>视为对象的表达方式,“ 这就是我知道我是否等于其他事物的方式 ”,而将IEqualityComparer<T>视为对象的表达方式,“ 这就是我知道是否两个其他情况都一样 ”。

For some good examples of how these two interfaces are used in the framework see: 有关在框架中如何使用这两个接口的一些良好示例,请参见:

Should you use the current state of an IEqualityComparer<T> to determine the hash code? 您是否应该使用IEqualityComparer<T>的当前状态来确定哈希码? If the state is at all mutable, then no! 如果状态是完全可变的,则否! Anywhere where the hash is used (eg HashSet<T> or Dictionary<T, V> ) the hash code will be cached and used for efficient lookup. 在使用哈希的任何地方(例如HashSet<T>Dictionary<T, V> ),哈希代码都将被缓存并用于有效查找。 If that hash code can change because the state of the comparer changes, that would totally destroy the usefulness of the data structure storing the hash. 如果由于比较器的状态改变而导致哈希码可以更改,那将完全破坏存储哈希值的数据结构的实用性。 Now, if the state is not mutable (ie it's set only when creating the comparer and cannot be modified throughout the lifetime of the comparer), then yes, you can, but I would still recommend against it, unless you have a really good reason. 现在,如果状态不是可变的(即仅在创建比较器时设置并且无法在比较器的整个生命周期内进行修改),那么可以,但是我仍然建议不要这样做,除非您有充分的理由。

Finally, you mentioned performance. 最后,您提到了性能。 Honestly, this sounds like premature optimization . 老实说,这听起来像是过早的优化 I'd recommend not worrying so much about performance until you can be sure that this particular line of code is causing a problem. 我建议您不要太担心性能,除非您可以确定这行特殊代码会引起问题。

If you are not using information from passed in obj arguments your hash code will not vary for different incoming objects and will not be useful. 如果您不使用obj参数中传递的信息,则您的哈希码对于不同的传入对象不会有所不同,并且将无用。 Comparer is not instance of object you want to get hash code for or compare to. 比较器不是要为其获取哈希码或与其进行比较的对象的实例。

Indeed you can use local fields of comaprer in GetHashCode and even can return MyData as hash code as shown in your sample - it will still satisfy GetHashCode requirement to "return the same value data for the same object". 实际上,您可以在GetHashCode使用comaprer的本地字段,甚至可以将MyData作为哈希代码返回,如您的示例中所示-它仍将满足GetHashCode要求,“为同一对象返回相同的值数据”。 But in your sample all hash codes will be the same for instance of comparer and hence using it for Dictionary will essentially turn dictionary into list. 但是在您的示例中,对于比较器实例,所有哈希码都将相同,因此将其用于Dictionary实质上会将字典转换为列表。

The same applies to Equals call - indeed you can return true all the time, but how useful it will be? 同样的方法适用于Equals通话-实际上您可以一直返回true ,但是它将有用吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为IEqualityComparer实现GetHashCode <T> 条件平等 - Implementing GetHashCode for IEqualityComparer<T> with conditional equality GetHashCode在IEqualityComparer中的作用是什么<T>在.NET 中? - What's the role of GetHashCode in the IEqualityComparer<T> in .NET? 通用 IEqualityComparer<T> 和 GetHashCode - Generic IEqualityComparer<T> and GetHashCode 实现 IEqualityComparer 时 GetHashCode 是否应该检查 null? - When Implementing IEqualityComparer Should GetHashCode check for null? 我什么时候应该使用 IEqualityComparer? C# - When should I use IEqualityComparer? C# 如何在Xamarin中将Google的API用于使用C#(而非Obj-C)的iOS应用 - How can I use Google's API in Xamarin for an iOS app using C# (not Obj-C) 如果我的类实现了IEqualityComparer,我应该实现非通用GetHashCode和Equals吗? <T> ? - Should I implement non-generic GetHashCode and Equals if my class implements IEqualityComparer<T>? 为什么当我调用此哈希集的删除操作时,它既不使用 gethashcode 也不使用相等实现? - Why when i call the remove operation of this hashset it doesn't use the gethashcode neither the equality implementation? 当我有此命令时,我将无法使用任何命令 - When i have this command, i can't use any command 当我定义IEqualityComparer时为什么不起作用<T> - Why doesn't Except work when I have defined IEqualityComparer<T>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM