|
Prev: How to determine if a property is inherited or not using reflection?
Next: Identifying the Publish Version of a ClickOnce app at Runtime
From: JonOfAllTrades on 20 Jun 2008 16:57 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!
From: Göran Andersson on 20 Jun 2008 19:02
JonOfAllTrades wrote: > 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<Key, Value> structure. > 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 IEqualityComparer<T> interface. I wrote an article about that a while ago: http://www.codeproject.com/KB/cs/dictionary_customkey.aspx > 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. -- Göran Andersson _____ http://www.guffa.com |