HashCode randomly changing on structures.
I've never in my career of coding have seen the behavior I'm about to describe so I'm hoping to learn something new... this is Unity3D btw...
In my code I am iterating a collection built on creation. I've confirmed that the objects are not being rebuilt at any time, and also the GetHashCode shown in this segment returns the same every time. The code below does not really matter a whole lot, just showing my work flow.
This is the SetIsKinematic method....
What's strange is whenever
_rigidbody.Velocity
(a structure) contains value the GetHashCode returns different. EG: if _rigidbody.velocity
is Vector3.zero
the hashcode is the same as what was called during the loop, but if it differs the hashcode does as well. I've found simply changing the struct to a class resolves the issue but I'm not sure why.
The read velocity
segment also always has the correct hashcode either way.6 Replies
and the REALLY stupid part is I have another variant of the same structure that works fine.
how is
GetHashCode()
implemented? do you rely on the default implementation?
the default-implementation for GetHashCode()
in structs says:
Action: Our algorithm for returning the hashcode is a little bit complex. We look for the first non-static field and get it's hashcode. If the type has no non-static fields, we return the hashcode of the type. We can't take the hashcode of a static member because if that member is of the same type as the original type, we'll end up in an infinite loop.
I'm not using any overrides but the value is definitely disappearing somewhere. The object the value was 'cached' on would change when a non-default value was being written.
I've never seen anything like this before.
I resolved it using a work-around. I'm going to share the information here to potentially help others.
Here's my structure before the fix. Minding, all I was doing was calling SetIsKinematic(true/false) that was causing the issue.
Here's the working version. I just moved the method call out.
Sounds like velocity is part of the hashcode calculation. Comparing the hash code of a struct to a class is kind of non-sensical since the default implementation for classes is just to use the reference instead of the actual data encapsulated by the class
HashCode calculations should really only be done on immutable data
Mutable structs are a common cause of issues related to HashCode calculations, like "losing" data inserted into a dictionary
@mtreit Still interesting that it works on one struct but not the other, and that moving the method out of the struct solved it.
The other struct had different value types but otherwise was exactly the same.
my
RigidbodyData
was being weird with the hashcodes while my Rigidbody2DData
was not.this probably depends on how
Rigidbody
/Rigidbody2D
calculate their HashCodes
since their HashCode would be included in the HashCode of their *Data-wrappers