![](/img/trans.png)
[英]Why I am getting this Resharper warning - does not override 'Object.Equals(object o) and 'Object.GetHashcode()'
[英]Why does KeyValuePair not override Equals() and GetHashCode()?
我打算在比较密集的代码中使用KeyValuePair
,并且很困惑地检查它是如何在.NET中实现的(s。下面)
为什么它不会为了效率而重写Equals
和GetHashCode
(而不是实现==
),而是使用基于慢反射的默认实现?
我知道结构/值类型有一个基于其GetHashCode()
和Equals(object)
方法的反射的默认实现,但我认为如果你做了很多比较,那么与覆盖相等相比它是非常低效的。
编辑我做了一些测试,发现在我的场景(WPF列表)中,默认的KeyValuePair
和我自己的结构覆盖GetHashCode()
和Equals(object)
的实现都比作为类的实现慢得多!
// ==++==
//
// 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/
所以,回答你的问题:为什么没有人这样做? 可能是因为他们不相信这样做是为了充分利用他们的时间,而不是他们为改进基类库而必须做的所有其他事情。 大多数人不会将键值对进行比较,因此优化它可能不是一个高优先级。
这当然是推测的; 如果你真的想知道为什么有些东西没有得到在某一天做的原因,你将要追查所有谁没有做那个动作,问他们还有什么他们正在做的人是更重要那天。
它是一个结构,Structs继承自ValueType
,该类型已经覆盖了Equals和GetHashCode的实现 。
它不支持==
,执行以下操作甚至不会编译
var result = new KeyValuePair<string, string>("KVP", "Test1") ==
new KeyValuePair<string, string>("KVP", "Test2");
您将收到错误“Operator'=='无法应用于KeyValuePair<string, string>
类型的操作数KeyValuePair<string, string>
和KeyValuePair<string, string>
”
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.