-2

I think this could be a common question but I failed to find any post about it.

I'm writing some pseudo code below. If you want to compile the code, please just ignore this post.

So say two classes: one base class and one child class. NOTE: both classes have override Equals() and GetHashCode() function to ensure equality with same property.

public class A // A has a string property of name
public class B:A // B has a string property of title

var a = new A{name = "bob"};
var b = new B{name = "bob", title = "em"};

Some code have a dictionary based on A

var dict = new Dictionary<A>();

Doing some adding stuff, for instance,

dict.Add(a);

However, the lookup function will raise KeyNotFoundException if i use a derived class searching with/o type cast

dict[b];

Dictionary will calculate the hashcode of B instead of A and raised the exception according to that.

A simple and awkward solution is to create a new instance of A based on B's property.

dict[new A{name = b.name}];

I wonder if there is any better solution?

Karl Jr.
  • 15
  • 4
  • 4
    A dictionary is a generic object of two types. Not just one `Dictionary`. Please correct the definition in your question to code that compiles. Otherwise it is difficult to help – Gilad Green Apr 01 '19 at 08:00
  • 1
    Please create a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). Your code does not compile, notr is it clear what your classes do. In particular your hashcode-implementations would be needed. – MakePeaceGreatAgain Apr 01 '19 at 08:01
  • "If you want to compile the code, please just ignore this post" - If this is just pseudo code then how do you want us to help you with an actual exception? Everything is kind of "working"/"valid" in pseudo.... Sorry but this is not really a well written SO question... Will be hard for anyone to help – Gilad Green Apr 01 '19 at 08:14
  • Thank you for your advice. But i think if the pseudo code can't help understanding the question, the answers will be surely useless as well. – Karl Jr. Apr 01 '19 at 08:23
  • After days of investigation and try out, an IEqualityComparer could be a good solution, which is suggested below. Again, thank you all for quick response, but also please, make sure you read the question and understand it. NOT just copy and paste the code and try to run it. – Karl Jr. Apr 16 '19 at 07:58

2 Answers2

0

You're confusing storing objects in a list, with the key of a dictionary. If you use objects as a key, you need to supply a reference to the same object - not just one with the same properties.

If you do this:

dict.Add(new A{name = "bob"}, someData);

and then do this

var result = dict[new A{name = "bob"}];

you'll get 'key not found' because the two new As are different objects.

Robin Bennett
  • 3,192
  • 1
  • 8
  • 18
  • Yeah, I forgot to mention that both classes have override Equality() and GetHashCode() functions for property comparison – Karl Jr. Apr 01 '19 at 08:18
0

Try creating an EqualityComparer, and pass an instance of it in the constructor of the dictionary.

class AEqualityComparer : IEqualityComparer<A>
{
    public bool Equals(A x, A y)
    {
        return x.Equals(y);
    }

    public int GetHashCode(A obj)
    {
        return obj.GetHashCode();
    }
}

var dict = new Dictionary<A, object>(new AEqualityComparer());
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104