Fixing Delegate's hash code's distribution (#11019)
authorPeter Smulovics <peter.smulovics@gmail.com>
Thu, 20 Apr 2017 22:46:39 +0000 (18:46 -0400)
committerJan Kotas <jkotas@microsoft.com>
Thu, 20 Apr 2017 22:46:39 +0000 (17:46 -0500)
Delegate's GetHashCode just returns the hash code of the delegate type. For a scenario where delegates are used as keys in a dictionary, this leads to obvious performance problems. We should look at coming up with a better GetHashCode that properly factors in the target object and method, in all of the various forms a delegate can take.

src/mscorlib/src/System/Delegate.cs
tests/src/CoreMangLib/cti/system/delegate/delegategethashcode1.cs

index de0ff65..75ec57a 100644 (file)
@@ -179,7 +179,10 @@ namespace System
             else
                 return unchecked((int)((long)this._methodPtrAux));
             */
-            return GetType().GetHashCode();
+            if (_methodPtrAux.IsNull())
+                return ( _target != null ? RuntimeHelpers.GetHashCode(_target) * 33 : 0) + GetType().GetHashCode();
+            else
+                return GetType().GetHashCode();
         }
 
         public static Delegate Combine(Delegate a, Delegate b)
index f2c5c51..05ba362 100644 (file)
@@ -218,7 +218,7 @@ namespace DelegateTest
         {
             bool retVal = true;
 
-            TestLibrary.TestFramework.BeginScenario("PosTest7:  Use the different instance's same instance method to create two delegate which delegate object is the same,their hashcode is equal");
+            TestLibrary.TestFramework.BeginScenario("PosTest7:  Use the different instance's same instance method to create two delegate which delegate object is the same, their hashcode is different");
 
             try
             {
@@ -226,7 +226,7 @@ namespace DelegateTest
                 booldelegate workDelegate = new booldelegate(new TestClass(1).StartWork_Bool);
                 booldelegate workDelegate1 = new booldelegate(new TestClass1(2).StartWork_Bool );
 
-                if (workDelegate.GetHashCode()!=workDelegate1.GetHashCode())
+                if (workDelegate.GetHashCode()==workDelegate1.GetHashCode())
                 {
                     TestLibrary.TestFramework.LogError("013", "HashCode is not excepted ");
                     retVal = false;