Generic Collection with reference types

E

Ethan Strauss

Hi,
I have just started using Generic Collections for .Net 2.0 and so far
they are working very nicely for me. But, I do have a couple of questions.
If I have a Generic collection which has a type which is a reference type,
is there a way to get Collection.ContainsKey(RefKey) and Collection[RefKey]
to work with different instances of equal keys?

For example, I have defined a class of "codon" and I have made a dictionary
private System.Collections.Generic.Dictionary<Codon, Double> CodonUsage;

I have two instances of CodonUsage and want to write codon similar to:
if (CodonUsageInstance1[ThisCodon] == CodonUsageInstance2[ThisCodon])
{
Do Stuff;
}

but this doesn't work. I am pretty sure that it is because the two different
instances of Codon Usage were populated with different instances of Codons
and thus they don't contain entries for arbitrary Codons even if they do
contain entries for Codons which are identical. My definition for Codon does
have an override of equals, so that different instances will evaluate to
equals correctly. I have similar issues with .ContainsKey.

Any help would be appreciated.

Thanks!

Ethan

Ethan Strauss Ph.D.
Bioinformatics Scientist
Promega Corporation
2800 Woods Hollow Rd.
Madison, WI 53711
608-274-4330
800-356-9526
(e-mail address removed)
 
J

Jon Skeet [C# MVP]

I have just started using Generic Collections for .Net 2.0 and so far
they are working very nicely for me. But, I do have a couple of questions.
If I have a Generic collection which has a type which is a reference type,
is there a way to get Collection.ContainsKey(RefKey) and Collection[RefKey]
to work with different instances of equal keys?

For example, I have defined a class of "codon" and I have made a dictionary
private System.Collections.Generic.Dictionary<Codon, Double> CodonUsage;

I have two instances of CodonUsage and want to write codon similar to:
if (CodonUsageInstance1[ThisCodon] == CodonUsageInstance2[ThisCodon])
{
Do Stuff;
}

You're not making a lot of sense - you're talking about "instances" of
CodonUsage, but it's a variable, not a type.

Have you overridden GetHashCode as well as Equals, by the way?
 
N

Nicholas Paldino [.NET/C# MVP]

Ethan,

This isn't an issue which involves generics, but rather, you want your
object identity to be defined by properties on the object, and not the
object reference, which it is by default.

You need to do two things. The first thing is to override the Equals
method in your Codon class so that it will compare an instance of the Codon
class to another that is passed to it, and determine, based on the values,
if they are the same or not.

The second thing you do is you need to override GetHashCode so that it
returns a value that is based on the hash of the values that your Codon
class is comparing for equality against. In other words, if you have a
field that is a string and a field that is an integer, then you need to
generate a hash code that is based on those two fields (assuming they are
used to test equality). You easily find hash code implementations through
google.

Once that is done, you should be able to use different instances of your
Codon class as keys in your dictionary, but have the same values, and get
the same results.

Hope this helps.
 
B

Bill Butler

Ethan Strauss said:
Hi,
I have just started using Generic Collections for .Net 2.0 and so
far they are working very nicely for me. But, I do have a couple of
questions. If I have a Generic collection which has a type which is a
reference type, is there a way to get Collection.ContainsKey(RefKey)
and Collection[RefKey] to work with different instances of equal keys?

For example, I have defined a class of "codon" and I have made a
dictionary
private System.Collections.Generic.Dictionary<Codon, Double>
CodonUsage;

I have two instances of CodonUsage and want to write codon similar to:
if (CodonUsageInstance1[ThisCodon] == CodonUsageInstance2[ThisCodon])
{
Do Stuff;
}
<snip>
OK perhaps I'm being particularly dense tonight since Jon and Nicholas
have already replied and haven't mentioned it but here goes.

I think your problem is that you are attempting to compare 2 doubles
using ==, and that is a no-no.

Bill
 
E

Ethan Strauss

Thanks to all.
Overriding GetHashCode was what I was missing. That did the trick.
Do any of you have the time/desire to explain what GetHashCode is used
for? Is there anything out there that really explains the guts of
collections and how all the bits and pieces work?
Thanks again,
Ethan

Nicholas Paldino said:
Ethan,

This isn't an issue which involves generics, but rather, you want your
object identity to be defined by properties on the object, and not the
object reference, which it is by default.

You need to do two things. The first thing is to override the Equals
method in your Codon class so that it will compare an instance of the
Codon class to another that is passed to it, and determine, based on the
values, if they are the same or not.

The second thing you do is you need to override GetHashCode so that it
returns a value that is based on the hash of the values that your Codon
class is comparing for equality against. In other words, if you have a
field that is a string and a field that is an integer, then you need to
generate a hash code that is based on those two fields (assuming they are
used to test equality). You easily find hash code implementations through
google.

Once that is done, you should be able to use different instances of
your Codon class as keys in your dictionary, but have the same values, and
get the same results.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Ethan Strauss said:
Hi,
I have just started using Generic Collections for .Net 2.0 and so far
they are working very nicely for me. But, I do have a couple of
questions. If I have a Generic collection which has a type which is a
reference type, is there a way to get Collection.ContainsKey(RefKey) and
Collection[RefKey] to work with different instances of equal keys?

For example, I have defined a class of "codon" and I have made a
dictionary
private System.Collections.Generic.Dictionary<Codon, Double> CodonUsage;

I have two instances of CodonUsage and want to write codon similar to:
if (CodonUsageInstance1[ThisCodon] == CodonUsageInstance2[ThisCodon])
{
Do Stuff;
}

but this doesn't work. I am pretty sure that it is because the two
different instances of Codon Usage were populated with different
instances of Codons and thus they don't contain entries for arbitrary
Codons even if they do contain entries for Codons which are identical. My
definition for Codon does have an override of equals, so that different
instances will evaluate to equals correctly. I have similar issues with
.ContainsKey.

Any help would be appreciated.

Thanks!

Ethan

Ethan Strauss Ph.D.
Bioinformatics Scientist
Promega Corporation
2800 Woods Hollow Rd.
Madison, WI 53711
608-274-4330
800-356-9526
(e-mail address removed)
 
J

Jon Skeet [C# MVP]

Overriding GetHashCode was what I was missing. That did the trick.
Do any of you have the time/desire to explain what GetHashCode is used
for? Is there anything out there that really explains the guts of
collections and how all the bits and pieces work?

The basic idea is that code is a quick way of narrowing down *possible*
matches, e.g. for keys in a hashtable.

Two keys which are equal should *definitely* have the same hashcode,
but two keys which aren't equal *might* have the same hashcode. In an
ideal world, hashcodes should be distributed such that two unequal keys
will almost always have different hashcodes.

When you look up a key in a hashtable, it first finds all the elements
with the right hashcode. After that it asks each of those whether or
not it's equal to the key you've passed in.
 

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