public class TestHashRace
{
private int cachedHash = 0;
private readonly object value;
public object Value
{
get { return value; }
}
public TestHashRace(object value)
{
this.value = value;
}
public override int GetHashCode()
{
if (cachedHash == 0) {
cachedHash = value.GetHashCode();
}
return cachedHash;
}
//Equals isn't part of the question, but since comments request it, here we go:
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != GetType()) return false;
return Equals((TestHashRace) obj);
}
protected bool Equals(TestHashRace other)
{
return Equals(value, other.value);
}
}
Here's simple test class.
Are we guaranteed that GetHashCode
will always return the same value?
And if we are, can someone point to some reference material which gives us this guarantee?
We aren't worried if it calculates hashcode for our value more than once, we just want to be sure that the returned value will always be the same.
Our class has to be immutable, while the cachedHash
field is mutable. Field cannot be volatile for performance reasons (the whole idea of this question and optimization we are questioning here). Value is immutable. And it has to be thread-safe.
We can live with potential hashcode recalculation when it will be 0 for some specifc values. We do not want to use nullable types or add additional fields for memory reasons (less memory used if we store only 1 int), so it has to be one int field to handle hashcode problem.
value
will change - anything holding an external reference of it could potentially modify it, rendering your cached hash value stale. Do you want the "same" hash code or do you want the "correct" hash? The only way this can work is if thevalue
object can notify the containing class if has been modified in a way that will alter its hash (or you need some way to guarantee thatvalue
will not be externally changed - store a clone or deep copy, etc). Does this need to be threadsafe? Too many questions here... – Unite