Repository navigation
Fixing Delegate's hash code's distribution - #11019
Conversation
|
Does not build... |
| return unchecked((int)((long)this._methodPtrAux)); | ||
| */ | ||
| return GetType().GetHashCode(); | ||
| return ( _target != null ? _target.GetHashCode() : 0) * 33 + GetType.GetHashCode(); |
There was a problem hiding this comment.
_target should be included in the hash code only if _methodPtrAux is null.
_target is overloaded field. It points other helper delegate objects when _methodPtrAux is non-null. The table at
coreclr/src/vm/comdelegate.cpp
Line 3471 in 5e03cb0
There was a problem hiding this comment.
So something like
if (_methodPtrAux.IsNull())
return ( _target != null ? _target.GetHashCode() : 0) * 33 + GetType().GetHashCode();
else
return GetType().GetHashCode();
would be more suitable?
| return unchecked((int)((long)this._methodPtrAux)); | ||
| */ | ||
| return GetType().GetHashCode(); | ||
| return ( _target != null ? _target.GetHashCode() : 0) * 33 + GetType.GetHashCode(); |
There was a problem hiding this comment.
Also, this needs to use RuntimeHelpers.GetHashCode so that it is not exposed to how custom types implement GetHashCode (e.g. they can implement it as throw new NotSupportedException()).
There was a problem hiding this comment.
I don't really understand this comment; you mean instead of GetType().GetHashCode()?
There was a problem hiding this comment.
Ah, to get the nonvirtual hashcode. Sure, updated.
eb612ef to
f521f86
Compare
|
Now it seems to build. |
|
Windows_NT x64 Release Priority 1 Build and Test fails due to Having a different hash code with my changes. They are clearly different delegates, does it makes sense to have the same return code? @jkotas if you agree on that, I'd modify the testcase as well so it would accept this (by basically flipping the comparism) I'm rereading Equals(), and found the snippet: and also looked at: from MultiCastDelegate.cs. That one also does go through the invocationlist and not the target. Does this mean that there is no easy way to solve this problem, and generally delegates shouldn't be used as keys in dictionaries? |
Agree - the test needs updating.
The invocationList will contain other Delegate object for MulticastDelegates, so it will end up calling your hashing function recursively.
I think your implementation works fine. It needs to be tested well though. |
|
Are automated tests possible? (Ie., can we write a test where it's guaranteed that X and Y will have different hashcodes?). If so it would be great to have a CoreFX PR up. |
|
@danmosemsft Actually there is a test already that fails now, DelegateGetHashCode.PosTest7 |
|
@jkotas I'm trying to figure out whether I need to update the Equals() method as well, can you advise. |
|
No change needed in |
|
Than this is up for merge. |
|
|
https://github.com/dotnet/corefx/blob/master/src/System.Runtime/tests/System/DelegateTests.cs would be a good place to add this test. |
|
To try your tests: |
|
@jkotas sure, will do |
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.
212b12a to
0badfee
Compare
|
@jkotas I rebased and squashed the commits Regards the other question - the test DelegateGetHashCode.PosTest7 does exactly this |
| booldelegate workDelegate1 = new booldelegate(new TestClass1(2).StartWork_Bool ); | ||
|
|
||
| if (workDelegate.GetHashCode()!=workDelegate1.GetHashCode()) | ||
| if (workDelegate.GetHashCode()==workDelegate1.GetHashCode()) |
There was a problem hiding this comment.
This has a very small probability of failing intermittently, but it is probably ok.
|
Thanks! |
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.
Fixes https://github.com/dotnet/coreclr/issues/9040