Using Structs As Dictionary Keys

J

JonOfAllTrades

Good afternoon. I think I've gotten to the bottom of an issue that's been
frustrating me this afternoon, but I find the result somewhat astonishing.
Can anyone explain to me why this is desirable behavior?

I need to look up values based on four integer keys. I've written two- and
three-key dictionary wrappers before, but they just gracefully wrap nested
Dictionaries, but that seems silly with four keys. So I created a simple
struct, wrote a decent hash function (thanks, Jon Skeet!), and started
populating data.
But I get nothing back. Apparently Dictionary requires that keys be not
only equal, but *the same object* to be considered the same! I thought I was
working around that by using a struct; they should always be handled purely
as values, such that I could freely create a key once when loading data, and
again later when retrieving, and the Dictionary would never know the
difference.

Am I missing something? Is it because the structs are being boxed to become
keys?

Doh! Need to override Equals. I assumed that structs, being value types,
would compare on the basis of fields by default, like an old-school Union
construct. I assumed wrongly.
Here's hoping this helps someone!
 
G

Göran Andersson

JonOfAllTrades said:
Good afternoon. I think I've gotten to the bottom of an issue that's been
frustrating me this afternoon, but I find the result somewhat astonishing.
Can anyone explain to me why this is desirable behavior?

I need to look up values based on four integer keys. I've written two- and
three-key dictionary wrappers before, but they just gracefully wrap nested
Dictionaries, but that seems silly with four keys. So I created a simple
struct, wrote a decent hash function (thanks, Jon Skeet!), and started
populating data.
But I get nothing back. Apparently Dictionary requires that keys be not
only equal, but *the same object* to be considered the same! I thought I was
working around that by using a struct; they should always be handled purely
as values, such that I could freely create a key once when loading data, and
again later when retrieving, and the Dictionary would never know the
difference.

Am I missing something? Is it because the structs are being boxed to become
keys?

No, the keys are not boxed. The key and the value are stored in a
KeyValuePair said:
Doh! Need to override Equals.

Yes, if you don't specify a comparer for the dictionary, it's using the
default EqualityComparer for the key, which will be the
ObjectEqualityComparer, which uses the Equals method for comparison.

As an alternative to implementing GetHashCode and Equals in the class,
you can create a comparer by making a class that implements the
I assumed that structs, being value types,
would compare on the basis of fields by default, like an old-school Union
construct. I assumed wrongly.

Sometimes it would be convenient to have a default comparison for
structures that would compare them on a field value basis, but on the
other hand that would mean that you would be forced to override that
comparison whenever you have a structure where a comparison like that
doesn't make sense. If you forgot to override the comparison, you could
get really strange results when the default comparer would use fields
that you really didn't intend it to use.
 

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