为什么KeyValuePair不覆盖Equals()和GetHashCode()? [英] Why does KeyValuePair not override Equals() and GetHashCode()?

查看:124
本文介绍了为什么KeyValuePair不覆盖Equals()和GetHashCode()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算在比较密集的代码中使用KeyValuePair,并且困惑地检查了它如何在.NET中实现(见下文).

为什么它不覆盖EqualsGetHashCode以提高效率(并且不实现==),而是使用基于慢反射的默认实现?

我知道struct/value类型的GetHashCode()Equals(object)方法具有基于反射的默认实现,但是如果您进行大量比较,我认为与覆盖相等相比效率很低.


编辑,我进行了一些测试,发现在我的方案(WPF列表)中,默认的KeyValuePair和我自己的实现覆盖GetHashCode()Equals(object)的结构的实现都更多然后慢了一个类的实现!


http://referencesource.microsoft.com/# mscorlib/system/collections/generic/keyvaluepair.cs,8585965bb176a426

// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
** Interface:  KeyValuePair
** 
** <OWNER>[....]</OWNER>
**
**
** Purpose: Generic key-value pair for dictionary enumerators.
**
** 
===========================================================*/
namespace System.Collections.Generic {

    using System;
    using System.Text;

    // A KeyValuePair holds a key and a value from a dictionary.
    // It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
    // and IReadOnlyDictionary<TKey, TValue>.
    [Serializable]
    public struct KeyValuePair<TKey, TValue> {
        private TKey key;
        private TValue value;

        public KeyValuePair(TKey key, TValue value) {
            this.key = key;
            this.value = value;
        }

        public TKey Key {
            get { return key; }
        }

        public TValue Value {
            get { return value; }
        }

        public override string ToString() {
            StringBuilder s = StringBuilderCache.Acquire();
            s.Append('[');
            if( Key != null) {
                s.Append(Key.ToString());
            }
            s.Append(", ");
            if( Value != null) {
               s.Append(Value.ToString());
            }
            s.Append(']');
            return StringBuilderCache.GetStringAndRelease(s);
        }
    }
}

解决方案

其他答案指出,您可以免费"获得相等性和哈希,因此您无需覆盖它们.但是,您得到的货款是多少?默认情况下,相等和哈希的实现方式(1)在某些情况下不是特别有效,并且(2)可以进行按位比较,因此可以执行诸如比较负零和正零双精度在逻辑上相等时是不同的事情.

如果您希望您的结构经常用于需要相等和哈希的上下文中,那么您应该编写两者的自定义实现并遵循适当的规则和准则.

https://ericlippert.com/2011/02/28/guidelines- and-rules-for-gethashcode/

因此,要回答您的问题:为什么没有人针对特定类型呢?可能是因为他们认为这样做与改进基础类库所需要做的所有其他事情相比,并不能很好地利用他们的时间.大多数人不会比较键值对是否相等,因此优化它可能不是一个高优先级.

这当然是推测性的;如果您实际上想知道某天某件事未完成的原因,那么您将必须找出所有所有人的人不做那个动作,然后问他们那天他们还在做什么,更重要.

I was going to use KeyValuePair in a comparison-intensive code and was perplexed checking how it is implemented in .NET (s. below)

Why does it not override Equals and GetHashCode for efficiency (and not implement ==) but instead uses the slow reflection-based default implementation?

I know that structs/value types have a default implementation based on reflection for their GetHashCode() and Equals(object) methods, but I suppose it is very inefficient compared to overriding equality if you do a lot of comparisons.


EDIT I made some tests and found out that in my scenario (WPF Lists) both default KeyValuePair and my own implementation of a struct overriding GetHashCode() and Equals(object) are both much more slow then an implementation as a class!


http://referencesource.microsoft.com/#mscorlib/system/collections/generic/keyvaluepair.cs,8585965bb176a426

// ==++==
// 
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// ==--==
/*============================================================
**
** Interface:  KeyValuePair
** 
** <OWNER>[....]</OWNER>
**
**
** Purpose: Generic key-value pair for dictionary enumerators.
**
** 
===========================================================*/
namespace System.Collections.Generic {

    using System;
    using System.Text;

    // A KeyValuePair holds a key and a value from a dictionary.
    // It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
    // and IReadOnlyDictionary<TKey, TValue>.
    [Serializable]
    public struct KeyValuePair<TKey, TValue> {
        private TKey key;
        private TValue value;

        public KeyValuePair(TKey key, TValue value) {
            this.key = key;
            this.value = value;
        }

        public TKey Key {
            get { return key; }
        }

        public TValue Value {
            get { return value; }
        }

        public override string ToString() {
            StringBuilder s = StringBuilderCache.Acquire();
            s.Append('[');
            if( Key != null) {
                s.Append(Key.ToString());
            }
            s.Append(", ");
            if( Value != null) {
               s.Append(Value.ToString());
            }
            s.Append(']');
            return StringBuilderCache.GetStringAndRelease(s);
        }
    }
}

解决方案

As the other answers point out, you get equality and hashing "for free", so you don't need to override them. However, you get what you pay for; the default implementations of equality and hashing are (1) not particularly efficient in some cases, and (2) may do bitwise comparisons, and hence can do things like compare negative zero and positive zero doubles as different when logically they are equal.

If you expect that your struct will frequently be used in contexts that require equality and hashing, then you should write custom implementations of both and follow the appropriate rules and guidelines.

https://ericlippert.com/2011/02/28/guidelines-and-rules-for-gethashcode/

So, to answer your question: why did no one do so for a particular type? Likely because they did not believe that doing so was a good use of their time compared to all the other things they had to do to improve the base class libraries. Most people do not compare key-value pairs for equality, so optimizing it was probably not a high priority.

This is of course conjectural; if you actually want to know the reason why something did not get done on a particular day, you're going to have to track down all the people who did not do that action and ask them what else they were doing that was more important on that day.

这篇关于为什么KeyValuePair不覆盖Equals()和GetHashCode()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆