Why doesn't KeyValuePair override Equals () and GetHashCode ()?

I was going to use KeyValuePair in code with intensive comparisons and was puzzled by checking how it is implemented in .NET (s. Below)

Why doesn't it override Equals and GetHashCode for efficiency (and doesn't implement == ), but instead uses the default implementation based on slow reflection?

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


EDIT . I did some tests and found out that in my script (WPF lists) both the default values ​​of KeyValuePair and my own implementation of the structure overriding GetHashCode() and Equals(object) are much slower, then the implementation is like 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); } } } 
+5
source share
3 answers

As the other answers point out, you get equality and hashing β€œfor free,” so you don't need to redefine them. However, you get what you pay for; by default, equality and hash implementations (1) are not particularly effective in some cases, and (2) can perform bitwise comparisons and, therefore, can do things like comparing negative zero and positive zero as different if they are logically equal.

If you expect your structure to be often used in contexts that require equality and hashing, then you should write your own implementations of both and follow the relevant rules and recommendations.

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

So, to answer your question: why has no one done this for a certain type? Probably because they did not believe that it was a good use of their time compared to everyone else, what they needed to do to improve the base class libraries. Most people do not compare key-value pairs for equality, so optimizing it is probably not a priority.

This, of course, is hypothesized; if you really want to find out the reason why something was not done on a certain day, you will need to track all the people who did not do this action and ask them what else they do, what was more important on that day.

+12
source

This is a struct that inherits Structs from ValueType , and this type already overrides the implementation of Equals and GetHashCode .

It does not support == , doing the following, does not even compile

 var result = new KeyValuePair<string, string>("KVP", "Test1") == new KeyValuePair<string, string>("KVP", "Test2"); 

You will receive an error message "The operator '==' cannot be applied to operands of the type KeyValuePair<string, string> and KeyValuePair<string, string> "

+6
source

KeyValuePair is an (Implicitly Inherits from ValueType ) structure, and Equality works just fine:

 var a = new KeyValuePair<string, string>("a", "b"); var b = new KeyValuePair<string, string>("a", "b"); bool areEqual = a.Equals(b); // true 

Link below Shows peer strategy:

1- The same link.

2- Can compare by bits.

3- Compare each field in the structure with reflection.

  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; } 
-3
source

All Articles