为什么KeyValuePair不会覆盖Equals()和GetHashCode()?

Mik*_*ail 7 .net c# value-type keyvaluepair

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

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

我知道结构/值类型有一个基于它们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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 15

正如其他答案所指出的那样,您可以"免费"获得相等和散列,因此您无需覆盖它们.但是,你得到你付出的代价; 平等和散列的默认的实现是:(1)不是特别有效在一些情况下,和(2)可以做逐位比较,并且因此可以不喜欢比较负零和正零逻辑时它们相等兼作不同.

如果您希望您的结构经常在需要相等和散列的上下文中使用,那么您应该编写两者的自定义实现,并遵循相应的规则和指南.

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

那么,回答你的问题:为什么没有人这样做?可能是因为他们不相信这样做是为了充分利用他们的时间,而不是他们为改进基类库而必须做的所有其他事情.大多数人不会将键值对进行比较,因此优化它可能不是一个高优先级.

这当然是推测的; 如果你真的想知道为什么什么事情也的原因没有得到在某一天完成的,你将要追查所有谁做的人不会做动作,问他们还有什么,他们这样做,是被放在更重要那天.

  • 同样可怕的是:如果你的结构使用`decimal`,你最终会得到`.Equals`返回true,但是对于像`1.0M`和`1.00M`这样的东西调用`GetHashCode`会得到不同的结果.http://www.volatileread.com/utilitylibrary/snippetcompiler?id=64818 (7认同)
  • @ user3185569:这不是有趣的案例.有趣的案例是:`struct S {public double d; 公共S(双d){this.d = d; Console.WriteLine(new S(-0.0).Equals(new S(0.0)));`即使显然两个双精度相等,也打印`False`. (4认同)

Sco*_*ain 7

它是一个结构,Structs继承ValueType而且该类型已经覆盖了Equals和GetHashCode的实现.

它不支持==,执行以下操作甚至不会编译

var result = new KeyValuePair<string, string>("KVP", "Test1") ==
         new KeyValuePair<string, string>("KVP", "Test2");
Run Code Online (Sandbox Code Playgroud)

您将收到错误"运算符'=='无法应用于类型的操作数KeyValuePair<string, string>KeyValuePair<string, string>"

  • `==`没有重载,所以它根本就没有编译. (3认同)
  • @Mikhail因为它不需要..NET框架从不在KeyValuePair上调用.GetHashCode或.Equals.它在TKey上调用它.框架从不使用它,因此没有理由覆盖它. (2认同)