1

I want to use a key (from new instance with the same property) to retrieve value. but it will get KeyNotFoundException.

class Program
{
    static void Main(string[] args)
    {
        Dictionary<Keyclass, ValueClass> dic = new Dictionary<Keyclass, ValueClass>()
        {
            { new Keyclass() { Key = "k1" }, new ValueClass() {Value = "v1"} },
            { new Keyclass() { Key = "k2" }, new ValueClass() {Value = "v2"} }
        };

        var key = new Keyclass() { Key = "k1" };
        var value = dic[key];
    }
}

 public class Keyclass
{
     public string Key { get; set; }
}

public class ValueClass
{
    public string Value { get; set; }
}
Charla
  • 77
  • 1
  • 1
  • 6
  • Thanks for the suggestion. anyhow it is a simple example that refer to my complex KeyClass. Why if KeyClass contains many properties (10+), is there any efficient way to override GetHashCode or Equal? – Charla Jul 15 '15 at 09:50

3 Answers3

3

Dictionaries use object.Equals and object.GetHashCode to compare keys so you'll need to implement those in your key class, or provide a IEqualityComparer implementation to the dictionary constructor.

public class Keyclass
{
    public string Key { get; set; }

    public override bool Equals(object other)
    {
      var otherKeyClass = other as Keyclass;
      return (otherKeyClass != null) && (otherKeyClass.Key == Key);
    }

    public override int GetHashCode()
    {
      return Key.GetHashCode();
    }
}
vc 74
  • 37,131
  • 7
  • 73
  • 89
2

As KeyClass is a class, the key is not found, as you create a new object (which has a different reference), even though their properties are the same. Now there are several options:

  1. Overwrite .Equals for the KeyClass, so your two object instances are treated the same and the key can be found.
  2. Instead of creating a new KeyClass instance, get it from the key collection:

    var key = dic.Keys.SingleOrDefault(p => p.Key == "k1");

  3. Define KeyClass as a struct instead of class, if possible. Structs are considered equal when all properties are equal.

LInsoDeTeh
  • 1,028
  • 5
  • 11
  • Upvoted :) "Structs are considered equal when all properties are equal" -- can u enlighten me a little more. – Newton Sheikh Jul 15 '15 at 09:34
  • 1
    You'll need to override GetHashCode too if you override Equals – vc 74 Jul 15 '15 at 09:34
  • @NewtonSheikh consider a `struct Vector { public int X; public int Y; }`. If you have `var vec1 = new Vector { X = 1, Y = 2 }` and `var vec2 = new Vector { X = 1, Y = 2 }`, then `vec1 == vec2` will return true, because the fields have the same values, which is not true when using classes instead (unless you overwrite `Equals`). – LInsoDeTeh Jul 15 '15 at 09:38
0

First of all why aren't you using Dictionary<string,string> instead of using wrapped string ?

Second if you really want to use your wrapper class you have to tell the wrapper class how to compare 2 instances of it by overriding Equals(Keyclass obj) and GetHashCode() Methods :

              public override bool Equals(object obj)
                {

                  return this.Key == ((KeyClass)obj).Key;
                }


       public override int GetHashCode()
         {
           int hash = 17;
           hash = hash * 23 + Key.GetHashCode();
           return hash;
         }
Bakri Bitar
  • 1,543
  • 18
  • 29
  • One would assume that the OP is going to expand the KeyClass (or is using it as a simple example). I also couldn't get your answer to work because there is no Equals method to override which has the Keyclass obj as a parameter. – Keithin8a Jul 15 '15 at 09:34
  • `Equals` parameter should be an `object` that you then cast into a `KeyClass` – Arthur Rey Jul 15 '15 at 09:37
  • If I have many properties in the KeyClass, how the GetHashCode() can be implemented in same way? – Charla Jul 15 '15 at 09:41
  • Yes you are right the Equals should take object as param ( I edited it ) – Bakri Bitar Jul 15 '15 at 09:47
  • @Charla check this out : http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode – Bakri Bitar Jul 15 '15 at 10:00