开发者

Cannot Find Key in Generic Dictionary [duplicate]

This question already has answers here: Dictionary KeyNotFoundException even though Key exists (3 answers) KeyNotFoundException in filled dictionary (2 answers) Closed 3 years ago.

I cannot find a dictionary entry by key. I have an interface like the following:

public interface IFieldLookup
{
    string FileName { get; set; }
    string FieldName { g开发者_JS百科et; set; }
}

Then I have a dictionary like so:

Dictionary<IFieldLookup, IField> fd

When I try to retrieve an element out of the dictionary by the key, I get a KeyNotFoundException. I am assuming that I have to implement some type of comparison - if my assumption is correct, what is the recommended way of implementing a comparison in this case?


use ContainsKey and override equals on the key class

Ok lets say this is our key class:

class Key
{
  public int KeyValue;
  public override bool Equals(object o)
  {
    return (((Key)o).KeyValue == KeyValue);
  }
}

now lets use the class as a key

Dictonary<Key, string> dict = new Dictonary<Key, string>();
Key k = new Key();
k.KeyValue = 123;
dict.Add(k, "Save me!");
Key k2 = new Key();
k2.KeyValue = 123;
if (dict.ContainsKey(k2))
{
  string value = dict[k2];
}


Since this is an interface rather than a class, you will have to define your equality operator for every class that implements the interface. And those operators will need to operate consistantly. (This would be much better if it were a class rather than an interface.)

You must override the Equals(object) and GetHashCode() methods on each class.

Probably something like this:

public override bool Equals(object obj)
{
   IFieldLookup other = obj as IFieldLookup;
   if (other == null)
        return false;
   return other.FileName.Equals(this.FileName) && other.FieldName.Equals(this.FieldName);
}

public override int GetHashCode()
{
    return FileName.GetHashCode() + FieldName.GetHashCode();
}

or this:

public override bool Equals(object obj)
{
   IFieldLookup other = obj as IFieldLookup;
   if (other == null)
        return false;
   return other.FileName.Equals(this.FileName, StringComparison.InvariantCultureIgnoreCase) && other.FieldName.Equals(this.FieldName, StringComparison.InvariantCultureIgnoreCase);
}

public override int GetHashCode()
{
    return StringComparer.InvariantCulture.GetHashCode(FileName) +
           StringComparer.InvariantCulture.GetHashCode(FieldName);
}

Depending on how you want it to behave.


Implement an instance of IEqualityComparer<T> (recommended by deriving from EqualityComparer<T> for its automatic implementation of IEqualityComparer as well) for the key type, and pass an instance to the dictionary constructor. This way you can implement the comparison consistently across multiple implementations of the interface.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜