Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hash codes for immutable types

Are there any considerations for immutable types regarding hash codes?

Should I generate it once, in the constructor?

How would you make it clear that the hash code is fixed? Should I? If so, is it better to use a property called HashCode, instead of GetHashCode method? Would there be any drawback to it? (Considering both would work, but the property would be recommend).

like image 674
Joan Venge Avatar asked Jun 01 '09 16:06

Joan Venge


People also ask

Is hashing immutable?

One of the key elements that make blockchain immutable is cryptographic hashes, which is why blockchain is immutable. The main advantage of hash is that it cannot be reverse-engineered. That's the reason why it is so popular.

Which of the following object can not be hashable in Python?

All immutable built-in objects in Python are hashable like tuples while the mutable containers like lists and dictionaries are not hashable. Objects which are instances of the user-defined class are hashable by default, they all compare unequal, and their hash value is their id().


2 Answers

Are there any considerations for immutable types regarding hash codes?

Immutable types are the easiest types to hash correctly; most hash code bugs happen when hashing mutable data. The most important thing is that hashing and equality agree; if two instances compare as equal, they should have the same hash code. (The reverse is not necessarily true; two instances that have the same hash need not be equal.)

Should I generate it once, in the constructor?

That's a performance optimizing technique; by doing so, you trade increased consumption of space (for the storage of the computed value) for a possible decrease in time. I never make performance optimizations unless they are driven by realistic, customer-focused performance tests that carefully measure the performance of both options against documented goals. You should do this if your carefully-designed experiments indicate that (1) failure to do so causes you to miss your goal, and (2) doing so causes you to meet your goal.

How would you make it clear that the hash code is fixed?

I don't understand the question. A changing hash code is the exception, not the rule. Hash codes are always supposed to be unchanging. If the hash code of an object changes then the object can get "lost" in a hash table, so everyone should assume that hash codes remain stable.

is it better to use a property called HashCode, instead of GetHashCode method?

What consumer of your object is going to say "well, I could call GetHashCode(), a method guaranteed to be on all objects, but instead I'm going to call this HashCode getter that does exactly the same thing" ? Do you have such a consumer in mind?

If you don't have any consumers of functionality, then don't provide the functionality.

like image 137
Eric Lippert Avatar answered Nov 08 '22 05:11

Eric Lippert


I wouldn't normally generate it in the constructor, but I'd also want to know more about the expected usage before deciding whether to cache it or not.

Are you expecting a small number of instances, which get hashed an awful lot and which take a long time to calculate the hash? If so, caching may be appropriate. If you're expecting a large number of potentially "throw-away" instances, I wouldn't bother caching.

Interestingly, .NET and Java made different choices for String in this respect - Java caches the hash, .NET doesn't. Given that many string instances are never hashed, and those which are hashed are often only hashed once (e.g. on insertion into the hash table) I think I favour .NET's decision here.

Basically you're trading memory + complexity against speed. As Michael says, test before making your code more complex. Of course in some cases (e.g. for a class library) you can't accurate predict the real-world usage, but in many situations you'll have a pretty good idea.

You certainly don't need a separate property though. Hash codes should always stay the same unless someone changes the state of the object - and if your type is immutable, you're already prohibiting that, therefore a user shouldn't expect any changes. Just override GetHashCode().

like image 35
Jon Skeet Avatar answered Nov 08 '22 05:11

Jon Skeet