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

时间:2016-07-07 16:19:43

标签: c# .net value-type keyvaluepair

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

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

我知道结构/值类型有一个基于其GetHashCode()Equals(object)方法的反射的默认实现,但我认为如果你进行大量的比较,那么与覆盖相等相比它是非常低效的

编辑我做了一些测试,发现在我的场景中(WPF列表)默认KeyValuePair和我自己的结构覆盖GetHashCode()和{{1}的实现并且比作为类的实现要慢得多!

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

Equals(object)

3 个答案:

答案 0 :(得分:14)

正如其他答案所指出的那样,您可以“免费”获得相等和散列,因此您无需覆盖它们。但是,你得到你付出的代价;相等和散列的默认实现是(1)在某些情况下不是特别有效,并且(2)可以进行逐位比较,因此可以执行诸如将负零和正零双精度在逻辑上它们相等时进行比较的事情。

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

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

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

这当然是推测的;如果你真的想知道为什么在某一天完成了某些事情的原因,那么你将不得不追踪所有那些做过的人不做那个动作并问他们当天还有什么其他更重要的事情。

答案 1 :(得分:7)

这是一个结构,Structs继承自localhost/:65 The specified value "{{email}}" is not a valid email address. http://localhost/css/bootstrap.min.css Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/app/lib/angular/angular.min.js Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/js/jquery.min.js Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/js/bootstrap.min.js Failed to load resource: the server responded with a status of 404 (Not Found) app.js:1 Uncaught ReferenceError: angular is not defined employees.js:1 Uncaught TypeError: Cannot read property 'controller' of undefined http://localhost/css/bootstrap.min.css Failed to load resource: the server responded with a status of 404 (Not Found) 并且类型为already overrides the implementation of Equals and GetHashCode

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

==

您将收到错误&#34;运营商&#39; ==&#39;无法应用于var result = new KeyValuePair<string, string>("KVP", "Test1") == new KeyValuePair<string, string>("KVP", "Test2"); KeyValuePair<string, string>&#34;

类型的操作数

答案 2 :(得分:-2)

KeyValuePair是一个结构(隐式继承自ValueType)并且Equality工作正常:

var a = new KeyValuePair<string, string>("a", "b");
var b = new KeyValuePair<string, string>("a", "b");

bool areEqual = a.Equals(b); // true

下面的参考显示了等于策略:

1-相同参考。

2-可以按位比较。

3-使用反射比较结构中的每个字段。

 public abstract class ValueType {

        [System.Security.SecuritySafeCritical]
        public override bool Equals (Object obj) {
            BCLDebug.Perf(false, "ValueType::Equals is not fast.  "+this.GetType().FullName+" should override Equals(Object)");
            if (null==obj) {
                return false;
            }
            RuntimeType thisType = (RuntimeType)this.GetType();
            RuntimeType thatType = (RuntimeType)obj.GetType();

            if (thatType!=thisType) {
                return false;
            }

            Object thisObj = (Object)this;
            Object thisResult, thatResult;

            // if there are no GC references in this object we can avoid reflection 
            // and do a fast memcmp
            if (CanCompareBits(this))
                return FastEqualsCheck(thisObj, obj);

            FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

            for (int i=0; i<thisFields.Length; i++) {
                thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
                thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);

                if (thisResult == null) {
                    if (thatResult != null)
                        return false;
                }
                else
                if (!thisResult.Equals(thatResult)) {
                    return false;
                }
            }

            return true;
        }