J
Jon Skeet [C# MVP]
Edward Diener said:hashtable[x] = "hello";
x.ChangeSomething();
x.ChangeSomethingElse();
then I wouldn't expect reading hashtable[x] to work, because the
hashcode would have changed by then, in my scheme of things.
The issue is that GetHashCode would return the same value since it is based
on an immutable field, but Equals would not. Then in case of a hash code
collision, the Equals method wouldn't be able to find the value.
I was suggesting basing GetHashCode and Equals on the same data, so
that they were always in step. ie Equals returning true => GetHashCode
returning the same value. That violates the GetHashCode constraint that
the same object always returns the same hash code, but only when the
values are changed.
The key in the hashtable wouldn't have changed but the original object which
serves as the key for finding the value could have changed if the object is
mutable.
But essentially that's then an entirely different object in .NET terms
- the "object" of a value type is precisely its values. When you change
the values, it's a different "object", just as:
int i = 5;
i = 4;
isn't changing the value of 5 to 4, it's just changing the value of i
to 4.
We are going around in circles here. My original point is simply that
classes which implement GetHashCode and Equals will not be in sync once one
of the mutable values upon which Equals is based changes.
*If* they abide by the rule which says that GetHashCode can't return
different values, which I've always said is a rule which I think can be
violated reasonably.
I am reticent to use Equals as my method to test for object equality, but
will create some other function for it in case an end-user needs to test
whether or not one of my components is "equal" to another of my components
of the same type. I continue to regard the doc that GetHashCode and Equals
must be in sync as flawed.
If it's a flaw, it's a necessary one. Essentially there are two
"views" of a key, and one of them is cached. The caching is necessary
for performance. If you keep the views in sync, the cache will get out
of date with regard to the original key. If you don't keep the views in
sync, the cache will get out of date with regard to a new but equal
key.