C# 在泛型词典中找不到键

C# 在泛型词典中找不到键,c#,generics,C#,Generics,我找不到按键排列的词典条目。我有一个如下所示的界面: public interface IFieldLookup { string FileName { get; set; } string FieldName { get; set; } } 那么我有一本这样的字典: Dictionary<IFieldLookup, IField> fd 字典 当我试图通过键从字典中检索一个元素时,我得到一个KeyNotFoundException。我假设我必须实现某种类型的比

我找不到按键排列的词典条目。我有一个如下所示的界面:

public interface IFieldLookup
{
    string FileName { get; set; }
    string FieldName { get; set; }
}
那么我有一本这样的字典:

Dictionary<IFieldLookup, IField> fd
字典
当我试图通过键从字典中检索一个元素时,我得到一个KeyNotFoundException。我假设我必须实现某种类型的比较-如果我的假设是正确的,那么在这种情况下实现比较的推荐方法是什么?

在key类上使用ContainsKey和override equals

好吧,假设这是我们的重点课程:

class Key
{
  public int KeyValue;
  public override bool Equals(object o)
  {
    return (((Key)o).KeyValue == KeyValue);
  }
}
现在让我们将该类用作键

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];
}
dictorial dict=new dictorial();
键k=新键();
k、 KeyValue=123;
dict.Add(k,“救救我!”);
键k2=新键();
k2.KeyValue=123;
if(dict.ContainsKey(k2))
{
字符串值=dict[k2];
}

在key类上使用ContainsKey和override equals

好吧,假设这是我们的重点课程:

class Key
{
  public int KeyValue;
  public override bool Equals(object o)
  {
    return (((Key)o).KeyValue == KeyValue);
  }
}
现在让我们将该类用作键

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];
}
dictorial dict=new dictorial();
键k=新键();
k、 KeyValue=123;
dict.Add(k,“救救我!”);
键k2=新键();
k2.KeyValue=123;
if(dict.ContainsKey(k2))
{
字符串值=dict[k2];
}

由于这是一个接口而不是一个类,因此必须为实现该接口的每个类定义相等运算符。这些运营商需要始终如一地运营。(如果它是一个类而不是一个接口,这会更好。)

必须重写每个类上的
Equals(object)
GetHashCode()
方法

可能是这样的:

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();
}
或者这个:

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);
}

取决于您希望它的行为。

因为这是一个接口而不是一个类,所以您必须为实现该接口的每个类定义相等运算符。这些运营商需要始终如一地运营。(如果它是一个类而不是一个接口,这会更好。)

必须重写每个类上的
Equals(object)
GetHashCode()
方法

可能是这样的:

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();
}
或者这个:

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);
}


取决于您希望它的行为方式。

为键类型实现一个实例(建议通过派生来自动实现),并将实例传递给字典构造函数。通过这种方式,您可以在接口的多个实现中一致地实现比较。

为键类型实现一个实例(建议通过派生来自动实现),并将实例传递给字典构造函数。通过这种方式,您可以跨接口的多个实现一致地实现比较。

实现IFieldLookup的类是什么样子的?它们是否覆盖Equals和/或GetHashCode方法?@Nick-它们没有-目前它们只实现IFieldLookup接口中的两个属性。@感谢所有人的反馈。实现IFieldLookup的类看起来像什么?他们是否重写Equals和/或GetHashCode方法?@Nick-他们没有-目前他们只实现IFieldLookup接口中的两个属性。@感谢所有人的反馈。“重写Equals”部分在这里很重要。@Petoj-你说要使用ContainsKey-你能解释一下吗?你是在推荐它,这样我就不会有例外了吗?如果是这样的话,我希望在这种情况下有一个例外。-1:使用
IEqualityComparer
。这里重要的是“覆盖等于”部分。@Petoj-你说使用ContainsKey-你能解释一下吗?你是在推荐它,这样我就不会有例外了吗?如果是这种情况,我希望在这种情况下有一个例外。-1:使用
IEqualityComparer
代替。-1:因为比较是特定于此词典的,所以使用必要的
IEqualityComparer
代替。@280Z28-OP没有声明比较将特定于此词典。比较很可能在程序中有其他用途,这些用途的语义需要相同..我理解@Jeffrey和@280Z28的意思。摘自IEquatable的MSDN页面的摘录很好地总结了这一点:IEquatable)接口定义了类型本身的相等性,而IEqualityComparer)接口是类型的外部接口,允许对同一类型使用许多不同的实现。谢谢你们两位的输入。请编辑你们的答案,以便我可以重新投票给你们-我选错了。-1:因为比较是针对本词典的,所以请使用必要的
IEqualityComparer
。@280Z28-OP没有说明比较是针对本词典的。比较很可能在程序中有其他用途,这些用途的语义需要相同..我理解@Jeffrey和@280Z28的意思。摘自IEquatable的MSDN页面的摘录很好地总结了这一点:IEquatable)接口定义了类型本身的相等性,而IEqualityComparer)接口是类型的外部接口,允许对同一类型使用许多不同的实现。谢谢你们的输入。请编辑您的答案,以便我可以重新投票给您-我选错了。-1这可能会导致在不涉及此特定词典的操作中使用不一致的相等比较器。@280Z28-阅读这些接口后,我看到MSDN说相等比较器)。默认属性:“检查类型T是否实现System.IEquatable泛型接口,如果是,则返回一个EqualityComparer),其中包含IEquitableEquals方法的植入。否则,它将返回一个EqualityComparer),正如T所提供的那样。“所以我猜应该做的是实现IEquatable并使用EqualityComparer.Default,如果需要不同的比较,则从EqualityComparer派生?对于本词典,您不会使用