> special code needs to exist to ensure that once GetHashCode() > has returned a value, that object instance must always return > the same value from later GetHashCode calls.
Nope. I know the docs say that GetHashCode must always return the same value, but they are wrong. See the "Documentation Rant" section in the second half of this: http://www.interact-sw.co.uk/iangblog/2004/06/21/gethashcode If you choose to follow the 'rule' that GetHashCode must always returns the same value, and for which you don't have a trivial GetHashCode that always returns a constant value, this commits you to writing immutable objects. (Or at least objects which can never change in a way that would change the outcome of Equals comparisons.) But as the posts from Microsoft employees linked to in that article above point out, that's not actually the intent. GetHashCode is allowed to return different values over time. For example, look at the IPAddress class: IPAddress ip = new IPAddress(0x12345678); IPAddress ip2 = new IPAddress(0x12345678); Console.WriteLine(ip.Equals(ip2)); Console.WriteLine(ip.GetHashCode()); Console.WriteLine(ip2.GetHashCode()); Console.WriteLine(); ip.Address = 0x87654321; Console.WriteLine(ip.Equals(ip2)); Console.WriteLine(ip.GetHashCode()); Console.WriteLine(ip2.GetHashCode()); Console.WriteLine(); IPAddress ip3 = new IPAddress(0x87654321); Console.WriteLine(ip.Equals(ip3)); Console.WriteLine(ip3.GetHashCode()); Console.WriteLine(); When I run this I get: True 305419896 305419896 False -2023406815 305419896 True -2023406815 Initially the two objects have the same value, so they compare as equal, and of course they therefore have the same hash code. I then change one of the values. (Note I'm not changing the object - it's the same pair of objects, I'm just mutating one of them.) It would make no sense for them to compare as equal now, and indeed we see 'False' returned. Notice that the hashcode of ip1 is now different. Why is it different? Well, what if we were to create a brand new IPAddress that happens to have the second address? Would you expect this third object to have the same hash as ip2, despite having a different value? How would you enforce that, other than by giving everything the same hashcode? Of course the third IPAddress object has the same address as the new address we gave the original ip object, so they both compare Equals as you see. And this of course requires them to have the same hash code. Note that this means you CANNOT store the original hash value and return it forever. If you do that you'll be breaking the rule that says "If Equals says two objects are equal, they must have the same hash code." This rule means that since the modified 'ip' object is equal to the 'ip3' object, they must have the same hash code. If 'ip' had held onto its original hashcode, it would be violating this rule. (Of course you might be wondering how I'm deciding which of the two mutually contradictory rules for GetHashCode it's safe to ignore, well first I refer you back to Brad Abrams post... But second, consider why these 'rules' were written - they're both for the benefit of hashtables. Hashtables require that equality of Equals always means equality of hashcodes. Hashtables also require that the hashcodes of objects use as keys do not change while. That's the rationale for the rule. However, you can also guarantee those two rules by ensuring that you stick to the 'equals implies same hashcode' rule, and by never modifying any object that's in use as a key.) So if you want to write mutable objects that implement GetHashCode you have two choices. (1) your GetHashCode could return a constant value, the same for all instances regardless of value, or (2) your object's hash code must change when the value changes in a way that affects the outcome of Equals. -- Ian Griffiths http://www.interact-sw.co.uk/iangblog/ > -----Original Message----- > From: Unmoderated discussion of advanced .NET topics. [mailto:ADVANCED- > [EMAIL PROTECTED] On Behalf Of J. Merrill > Sent: 27 June 2005 20:37 > To: [email protected] > Subject: Re: [ADVANCED-DOTNET] GetHashCode() method > > At 02:49 PM 6/27/2005, Frans Bouma wrote (in part) > >> There's been some discussion lately regarding the > >> Object.GetHashCode() method. > >> > >> I think the concensus is pretty clear: for best reliability, > >> classes that implement GetHashCode() should be immutable. > > > > Why? you can also get dupes with GetHashCode. It's not as if it's > a magic value. The point is though that if you use it for identification, > realize that the identification is not unique, as a risk for dupes is > there. > > I think the right way to say it is that if the GetHashCode result is > computed from values of one or more properties (or fields) of the object, > those values must be immutable -- either that, or special code needs to > exist to ensure that once GetHashCode() has returned a value, that object > instance must always return the same value from later GetHashCode calls. > > It seems to me that it would be perfectly acceptable to implement > GetHashCode so that the first time it's called, it computes, records, and > returns an at-least-somewhat random value (perhaps based on the current > value of one or more properties). On subsequent calls, the value returned > the first time is returned again (even if the values the initial > computation had been based on has changed). Is there a case where this > violates either the spirit or the letter of the GetHashCode contract? > > >> Other than the Hashtable and ProperytCollection classes, does > >> anyone know where GetHashCode() is used in the framework with > >> a collection of references? > > > > IMHO everywhere where Equals is used as well, as you have to > override GetHashCode as well if Equals is overriden. Equals is used in > IndexOf, Contains of ArrayList > > > > Frans > > > J. Merrill / Analytical Software Corp > > =================================== > This list is hosted by DevelopMentor(r) http://www.develop.com > > View archives and manage your subscription(s) at > http://discuss.develop.com =================================== This list is hosted by DevelopMentorĀ® http://www.develop.com View archives and manage your subscription(s) at http://discuss.develop.com
