.NET Forum / .NET Framework / New Users / August 2004
Hashtables
|
|
Thread rating:  |
Brandon Owensby - 14 Jun 2004 03:41 GMT Is it ok to use an object whos equality is determined by reference as the key to a hashtable?
Thanks, Brandon
Brandon Owensby - 14 Jun 2004 06:26 GMT To add to my question....if it isn't a good idea to use a reference type object as a key to a hashtable could someone give me and idea on how to deal with a particular problem.
I have some code set up where if you choose a row in a datagrid it will load a window about that code. If you go back to the original window without closing the child window and proceed to choose the same row again later it will do a look up in a hashtable using the selected datarow as a key...if the hashtable contains a entry for that key (which is inserted when you open the first window) it brings that window into focus instead of loading a new window.
Since I'm not allowed to add a column (due to administrative constraints) to the table in question and the primary key can be more than one column how could I go about doing a similar thing?
I think I have a few ideas that may work...I'll have to go over them in my head. Please don't spend any great deal of time on this...just let me know any ideas that might pop into mind....or something you've done if you've run into a similar situation.
Thanks for anytime given.
William Stacey [MVP] - 14 Jun 2004 06:45 GMT Depends on what your doing with objects. The GetHashCode of a straight object type is its ref value. If you up-cast to object, but the derived object has GetHashCode overriden, then you get what that method returns (i.e. string will return a calc hash based on each char in the string, etc.) So if you have two object (for example) that point to same string, then you get the same hash code and equal method will return true, so you can't add both to the hashtable. Maybe example of what your trying. hth.
object o1 = new object(); object o2 = new object(); string s = "name"; object o3 = s; object o4 = (object)s; Console.WriteLine("o1:"+o1.GetHashCode()); Console.WriteLine("o2:"+o2.GetHashCode()); Console.WriteLine("s:"+s.GetHashCode()); Console.WriteLine("o3:"+o3.GetHashCode()); Console.WriteLine("o4:"+o4.GetHashCode()); Console.WriteLine("o3.equal(o4):"+o3.Equals(o4));
o1:94 o2:93 s:2087876002 o3:2087876002 o4:2087876002 o3.equal(o4):True
 Signature William Stacey, MVP
> Is it ok to use an object whos equality is determined by reference as the > key to a hashtable? > > Thanks, > Brandon Jon Skeet [C# MVP] - 14 Jun 2004 08:20 GMT > Is it ok to use an object whos equality is determined by reference as the > key to a hashtable? That's okay - but you should override GetHashCode, as the default implementation is basically useless as it doesn't guarantee to give consistent results.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Jerry Pisk - 14 Jun 2004 12:58 GMT Read the thread about "Complex Objects as Hash Keys". If you use the default GetHashCode then it's not ok to use those objects as keys in a hash table.
Jerry
> Is it ok to use an object whos equality is determined by reference as the > key to a hashtable? > > Thanks, > Brandon Brandon Owensby - 14 Jun 2004 17:34 GMT That thread was the whole reason I put this post on here. I know Randy...he is in my organization. I wanted to find out a way to use a complex reference equated object as a key to some other object. I have already read everything and done research on my own and understand the deal with the base GetHashCode method. I cannot override it for the only thing I have to go by in creating a HashCode is the reference. If I have an object A and an object B then they are only deemed to be equal if they both point to the same thing. It doesn't matter if they point to 2 different things that have similar of not same values. I'm thinking of just using a datatable. However can you not use a reference object as the primary key of a datatable either?
Jerry Pisk - 14 Jun 2004 19:31 GMT Being able to use an object as a key in a database has nothing to do with how equality is handled. I think it's getting a little mixed up here. As for using a reference address as a hash code - no you can't use that, because it changes over the lifetime of an object.
Jerry
> That thread was the whole reason I put this post on here. I know > Randy...he [quoted text clipped - 13 lines] > datatable > either? Brandon Owensby - 14 Jun 2004 20:04 GMT First of all it says in the help you pointed us to earlier that you must override the Equals method if you override the GetHashCode method.
It also states that you can use the base method if the object defines equality by reference.
"For derived classes of Object, GetHashCode can delegate to the Object.GetHashCode implementation, if and only if that derived class defines value equality to be reference equality and the type is not a value type."
Furthermore the statement you quoted from the help in the other newsgroup thread onlly states that it can't garuntee uniqueness or consistency for everything. This is why things like string, ints, datetime would override it. Objects that can't use values to determine equality and instead use reference don't need to override the base function.
Also Mattias Sjorgren said the following statement in the other thread which was never commented on
"If I recall correctly, the v1.x framework's Object.GetHashCode implementation returns the syncblock index, which should be consistent."
He like you has the title MVP. I bring this up because I understand tha garbage collection can change references....however this guy seems to say that the actual reference is not used in the HashCode but instead this syncblock index. What about that?
Thanks again for your time.
Brandon
Brandon Owensby - 16 Jun 2004 16:13 GMT Could anyone give me some alternatives if no one is gonna help figure out how to has a reference object. Can reference objects be used as the primary key for a datatable?
mikeb - 16 Jun 2004 18:56 GMT > Could anyone give me some alternatives if no one is gonna help figure out > how to has a reference object. Can reference objects be used as the primary > key for a datatable? Reference objects can be used as the primary key. If you're worried about the default Object.GetHashCode() implementation breaking when an object is moved as a result of garbage collect, then you don't need to worry. Object.GetHashCode() will return the same result for a particular object instance regardless of whether or not the object has been moved in real memory. To do otherwise would be a completely broken GetHashCode() implementation.
I think that the documentation for Object.GetHashCode() is misleading, incorrect, self-contradicting and/or poorly worded. For example, it says in one spot:
The default implementation of GetHashCode does not guarantee uniqueness or consistency; therefore, it must not be used as a unique object identifier for hashing purposes.
But it later says:
For derived classes of Object, GetHashCode can delegate to the Object.GetHashCode implementation, if and only if that derived class defines value equality to be reference equality and the type is not a value type.
So, is Object.GetHashCode() OK to use or not? One thing they mention is a problem with uniqueness. Hashcodes do not need to be unique to an object instance. An implementation of GetHashCode() that simply returned 1 would fulfill the contract (but it would result in a poor hashtable). I'm not sure what they mean by 'consistency', but I think it's a poor attempt to indicate that Object.GetHashCode() will not necessarily return the same value for 2 different objects that are equal (in some way other than reference equality).
I think what the doc is trying to say (overall - not just the snippets above) is that the default GetHashCode() implementation is not particularly good (ie., not a random distribution), and that it's wholly inappropriate for types which define equality in some way other than reference equality.
Now, if the reference objects that you want to use as a key have overridden the Equals() method so something other than reference equality is used, then that class must also override the GetHashCode() method so that instances which are equal also return the same result form GetHashCode().
If the class being used as a Hashtable key is mutable in a way that an instance can be modified such that it would no longer be equal to that instance's previous state, then it should only be used as a Hashtable key if you know that it will not be modified while being used as a key. Actually, it's probably not a good idea to use such a class as a key. I'm sure that this is one of the many reasons why the String class is not mutable.
 Signature mikeb
Brandon Owensby - 16 Jun 2004 19:46 GMT I agree with you on that. Unfortunatly I don't think my boss will go with the idea of the hashtable until a microsoft expert or MVP or whatever they are called. Emails him and tells him its ok...and explains to him what you said to me. If there is any body out there that could do this I'd be much appreciative if a microsoft official would jump in on this and back Mike and myself up. Unless Mike you are a microsoft person? It doesn't say that on the bottom of your post though. You have given me hope though. Thanks.
Brandon
mikeb - 16 Jun 2004 20:26 GMT > I agree with you on that. Unfortunatly I don't think my boss will go with > the idea of the hashtable until a microsoft expert or MVP or whatever they [quoted text clipped - 3 lines] > myself up. Unless Mike you are a microsoft person? It doesn't say that on > the bottom of your post though. You have given me hope though. Thanks. Sorry, I'm not from MS. If you're an MSDN subscriber you can register an email alias that will flag your newsgroup posts for a Microsoft response:
http://msdn.microsoft.com/newsgroups/managed/
Or maybe an MVP can convince someone from MS to post a definitive response (either here or in a weblog we can be pointed to).
 Signature mikeb
Jon Skeet [C# MVP] - 16 Jun 2004 22:35 GMT > I agree with you on that. Unfortunatly I don't think my boss will go with > the idea of the hashtable until a microsoft expert or MVP or whatever they [quoted text clipped - 3 lines] > myself up. Unless Mike you are a microsoft person? It doesn't say that on > the bottom of your post though. You have given me hope though. Thanks. I'll see if I can get a definitive answer from MS. I'll go by the slightly odd route of lodging a sort of bug request on the MSDN documentation itself as being misleading. I'll report back any conclusions. I have a suspicion of what *might* be meant by "not consistent" though: different runs containing the same data may well produce different hashcodes, because it's dependent on the reference. So, it may be inconsistent across that, but any one object returns the same hashcode throughout its lifetime.
I'll see what I can do, anyway - and escalate it via my MVP lead if I can't get anywhere.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Brandon Owensby - 17 Jun 2004 01:38 GMT Brandon Owensby - 18 Aug 2004 19:43 GMT What happened? I haven't heard anything? Could you at least send me a response saying you couldn't find out anything?
Thanks, Brandon
Jon Skeet [C# MVP] - 18 Aug 2004 20:00 GMT > What happened? I haven't heard anything? Could you at least send me a > response saying you couldn't find out anything? It would have helped if you'd quoted a post so I'd have known you were talking about something I'd posted. It's been rather a long time - I'd forgotten about it, to be honest.
I haven't found anything out yet, but I'll make a note to ask again.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Jon Skeet [C# MVP] - 23 Aug 2004 18:01 GMT > > What happened? I haven't heard anything? Could you at least send me a > > response saying you couldn't find out anything? [quoted text clipped - 4 lines] > > I haven't found anything out yet, but I'll make a note to ask again. I've had a response from my MVP lead:
<quote> Rafael, John's original statement is the correct interpretation. We ran into a problem in Everett and had to change the algorithm, and we wanted to ensure that we made it clear people shouldn't expect specific hashcodes for things. Even in the scenario he points out (running an app again) the hash might change. </quote>
In other words, don't try to store hashcodes and hope that they'll be the same on the next run, but it's okay to assume object.GetHashCode() won't return different values for the same actual object instance. You can safely use Hashtable.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Brandon Owensby - 24 Aug 2004 01:26 GMT Thanks alot!! To make sure I understand what I'm suppose to get from that...its saying that if I have a hashtable I can use an object defined by the instance as the hashkey for that hashtable....I just shouldn't store the hash key in database or anything. Correct?
Thanks for your help!!!, Brandon Owensby
Jon Skeet [C# MVP] - 24 Aug 2004 03:04 GMT > Thanks alot!! To make sure I understand what I'm suppose to get from > that...its saying that if I have a hashtable I can use an object > defined by the instance as the hashkey for that hashtable....I just > shouldn't store the hash key in database or anything. Correct? You shouldn't store the hash *code* in a database or anything like that. You can store the key as (say) a string and then recreate the hashtable later, just don't rely on it having the same hash code that it did before.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Brandon Owensby - 24 Aug 2004 16:26 GMT I'm not planning on storing it anywhere. I just wanna be able to take a class....that is base on instance....not value and use is as a key to a hashtable. In otherwords...as an example:
Form form = ???;
Hashtable hashtable = new Hashtable();
hashtable.Add(form, somevalue);
somevalueholder = hashtable[form];
I have done this without problem....but my supervisor was concerned it wouldn't always work. I am seeming to understand that that is fine. The key doesn't have to be instance based.
Thanks again for your help.
Brandon
Jon Skeet [C# MVP] - 24 Aug 2004 16:53 GMT > I'm not planning on storing it anywhere. I just wanna be able to take a > class....that is base on instance....not value and use is as a key to a [quoted text clipped - 11 lines] > wouldn't always work. I am seeming to understand that that is fine. The > key doesn't have to be instance based. Well, I don't know what you mean by "that is base on instance" but the above will be fine.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Brandon Owensby - 24 Aug 2004 18:46 GMT Thanks alot....and to clarify...what I meant by "base on instance" which should of read "based on instance" is that something that isnt' based on the value of the object such as int or decimal but by the instance of the object. for a form is never equal to a form based on values...only on instance.
Thanks again for all your help.
Brandon Owensby
PS - Is this information based only on Everret or does it apply to VS 2003 C# .Net 1.1 as well?
Jon Skeet [C# MVP] - 24 Aug 2004 19:42 GMT > Thanks alot....and to clarify...what I meant by "base on instance" which > should of read "based on instance" is that something that isnt' based on the [quoted text clipped - 8 lines] > PS - Is this information based only on Everret or does it apply to VS 2003 > C# .Net 1.1 as well? Everett *is* VS.NET 2003/.NET 1.1. However, I think it'll be safe to rely on this behaviour forever.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|