Hashtables

B

Brandon Owensby

Is it ok to use an object whos equality is determined by reference as the
key to a hashtable?

Thanks,
Brandon
 
B

Brandon Owensby

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.
 
W

William Stacey [MVP]

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
 
J

Jon Skeet [C# MVP]

Brandon Owensby said:
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.
 
J

Jerry Pisk

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
 
B

Brandon Owensby

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?
 
J

Jerry Pisk

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
 
B

Brandon Owensby

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
 
B

Brandon Owensby

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?
 
M

mikeb

Brandon said:
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.
 
B

Brandon Owensby

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
 
M

mikeb

Brandon said:
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.

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).
 
J

Jon Skeet [C# MVP]

Brandon Owensby said:
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.

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.
 
B

Brandon Owensby

What happened? I haven't heard anything? Could you at least send me a
response saying you couldn't find out anything?

Thanks,
Brandon
 
J

Jon Skeet [C# MVP]

Brandon Owensby said:
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.
 
J

Jon Skeet [C# MVP]

Jon Skeet said:
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.

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.
 
B

Brandon Owensby

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
 
J

Jon Skeet [C# MVP]

Brandon Owensby said:
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.
 
B

Brandon Owensby

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top