【问题标题】:c# "The given key was not present in the dictionary" when key is a type itselfc#“给定的键不在字典中”当键本身是一个类型时
【发布时间】:2015-12-05 09:18:14
【问题描述】:

这是我的代码:

public class MyKeyType
{
    public int x;
    public string operationStr;
}

private static Dictionary<MyKeyType, List<int>> m_Dict = new Dictionary<MyKeyType, List<int>>
{
    { new MyKeyType { x = MyValsType.File, operationStr = "LINK" },   new List<int> { 1,2,3,4,5  }  }, 
    { new MyKeyType { x = MyValsType.File, operationStr = "COPY" },   new List<int> { 10,20,30,40,50  }  }, 
    .....
}

List<int> GetValList( int i, string op)
{ 
    // The following line causes error:
    return ( m_Dict [ new MyKeyType { x = i, operationStr = op } ] );
}

但是当我调用时出现错误“字典中不存在给定的键”:

GetValList( MyValsType.File, "LINK");

你能说出原因吗?非常感谢。

【问题讨论】:

  • 您将新对象传递给字典,因此它不存在。
  • 为什么?因为字典中不存在给定的键。我猜您想找到其属性(xoperationStr)与上一个条目匹配的键,但这并不意味着该条目是相同的。例如:MyKeyType test = new MyKeyType { x = 1, operationStr = "1" }; m_Dict.Add(test, new List&lt;int&gt;() { 1, 2, 3 }); 如果你现在做MyKeyType test0 = new MyKeyType {x = 1, operationStr = "1" }; List&lt;int&gt; test2 = m_Dict[test0]; 你会得到一个错误。顺便说一句,下次你应该试着做一个小努力清楚地问清楚,例如像这样一个简单的例子。
  • @MaximGoncharuk 建议明确地重新定义给定变量很少是一个好建议。你不知道为什么 OP 想要这个数据结构。
  • 有多种选择可以完成您的工作。您可以查找与给定属性匹配的条目(通过常规循环或 LINQ);或者您可以重新定义您的类,以便立即支持某些比较(例如:stackoverflow.com/questions/4188013/…)。
  • 您没有覆盖 Equals 和 GetHashCode,也没有为字典提供 IEqualityComparer,因此 MyKeyType 类型的新对象永远不会匹配字典中存储的对象。像这样暴露字段的类不是字典键的理想选择,顺便说一句,更改字段太容易使字典条目无法挽回地丢失。

标签: c# dictionary key


【解决方案1】:

当您使用类作为字典的键时,该类必须正确实现GetHashCode() 和 Equals:字典调用这两个方法来理解“那个键”与“那个另一个键”相同:如果 2 个实例 xyGetHashCode()x.Equals(y) == true; 返回相同的值,则 2 个键匹配。

不提供 MyKeyType 类中的两个覆盖将导致在运行时调用 object.GetHashCode()object.Equals:只有当 x 和 y 是对同一实例的引用时,它们才会返回匹配项(即 @987654329 @)

许多 .Net 框架类型(例如字符串、数字类型、日期时间等)都正确实现了这两种方法。对于您定义的类,您必须在代码中实现它们

【讨论】:

    【解决方案2】:

    如果您能够使用 LINQ,您可以将 GetValList() 更改为:

     static List<int> GetValList(int i, string op)
        {
           return m_Dict.Where(x => x.Key.x == i && x.Key.operationStr.Equals(op)).Select(x => x.Value).FirstOrDefault(); 
        }
    

    【讨论】:

    • 是的,LINQ 方法是最简单的一种。
    猜你喜欢
    • 2014-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 2020-02-20
    • 2012-02-18
    相关资源
    最近更新 更多