简体   繁体   English

System.Collections.Generic.KeyNotFoundException:给定的键不在字典中

[英]System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary

I receive the above error message when performing a unit test on a method. 我在对方法执行单元测试时收到上述错误消息。 I know where the problem is at, I just don't know why it's not present in the dictionary. 我知道问题出在哪里,我只是不知道为什么它不在字典中。

Here is the dictionary: 这是字典:

var nmDict = xelem.Descendants(plantNS + "Month").ToDictionary(
    k => new Tuple<int, int, string>(int.Parse(k.Ancestors(plantNS + "Year").First().Attribute("Year").Value), Int32.Parse(k.Attribute("Month1").Value), k.Ancestors(plantNS + "Report").First().Attribute("Location").Value.ToString()),
    v => { 
             var detail = v.Descendants(plantNS + "Details").First();
             return new HoursContainer
             {
                 BaseHours = detail.Attribute("BaseHours").Value,
                 OvertimeHours = detail.Attribute("OvertimeHours").Value,
                 TotalHours = float.Parse(detail.Attribute("BaseHours").Value) + float.Parse(detail.Attribute("OvertimeHours").Value)
             };
         });

var mergedDict = new Dictionary<Tuple<int, int, string>, HoursContainer>();

foreach (var item in nmDict)
{
    mergedDict.Add(Tuple.Create(item.Key.Item1, item.Key.Item2, "NM"), item.Value);
}


var thDict = xelem.Descendants(plantNS + "Month").ToDictionary(
    k => new Tuple<int, int, string>(int.Parse(k.Ancestors(plantNS + "Year").First().Attribute("Year").Value), Int32.Parse(k.Attribute("Month1").Value), k.Ancestors(plantNS + "Report").First().Attribute("Location").Value.ToString()),
    v => {
             var detail = v.Descendants(plantNS + "Details").First();
             return new HoursContainer
             {
                 BaseHours = detail.Attribute("BaseHours").Value,
                 OvertimeHours = detail.Attribute("OvertimeHours").Value,
                 TotalHours = float.Parse(detail.Attribute("BaseHours").Value) + float.Parse(detail.Attribute("OvertimeHours").Value)
             };
         });

foreach (var item in thDict)
{
    mergedDict.Add(Tuple.Create(item.Key.Item1, item.Key.Item2, "TH"), item.Value);
}
        return mergedDict;                                 

} }

and here is the method that is being tested: 这是正在测试的方法:

protected IList<DataResults> QueryData(HarvestTargetTimeRangeUTC ranges,
        IDictionary<Tuple<int, int, string>, HoursContainer> mergedDict)
{            
    var startDate = new DateTime(ranges.StartTimeUTC.Year, ranges.StartTimeUTC.Month, 1);
    var endDate = new DateTime(ranges.EndTimeUTC.Year, ranges.EndTimeUTC.Month, 1);
    const string IndicatorName = "{6B5B57F6-A9FC-48AB-BA4C-9AB5A16F3745}";

    DataResults endItem = new DataResults();
    List<DataResults> ListOfResults = new List<DataResults>();                               

    var allData =

    (from vi in context.vDimIncidents
    where vi.IncidentDate >= startDate.AddYears(-3) && vi.IncidentDate <= endDate
        select new
        {
            vi.IncidentDate,
            LocationName = vi.LocationCode,
            GroupingName = vi.Location,
            vi.ThisIncidentIs, vi.Location
        });

    var finalResults = 

            (from a in allData
            group a by new { a.IncidentDate.Year, a.IncidentDate.Month, a.LocationName, a.GroupingName, a.ThisIncidentIs, a.Location }
                into groupItem
            select new 
            {
                Year = String.Format("{0}", groupItem.Key.Year),
                Month = String.Format("{0:00}", groupItem.Key.Month),
                groupItem.Key.LocationName,
                GroupingName = groupItem.Key.GroupingName,
                Numerator = groupItem.Count(),
                Denominator = mergedDict[Tuple.Create(groupItem.Key.Year, groupItem.Key.Month, groupItem.Key.LocationName)].TotalHours,  
                IndicatorName = IndicatorName,                        
            }).ToList();


    for (int counter = 0; counter < finalResults.Count; counter++)
    {
        var item = finalResults[counter];
        endItem = new DataResults();
        ListOfResults.Add(endItem);
        endItem.IndicatorName = item.IndicatorName;
        endItem.LocationName = item.LocationName;
        endItem.Year = item.Year;
        endItem.Month = item.Month;
        endItem.GroupingName = item.GroupingName;
        endItem.Numerator = item.Numerator;
        endItem.Denominator = item.Denominator;               
    }

    foreach(var item in mergedDict)
    {
        if(!ListOfResults.Exists(l=> l.Year == item.Key.Item1.ToString() && l.Month == item.Key.Item2.ToString()
                && l.LocationName == item.Key.Item3))
        {
            for (int counter = 0; counter < finalResults.Count; counter++)
            {
                var data = finalResults[counter];
                endItem = new DataResults();
                ListOfResults.Add(endItem);
                endItem.IndicatorName = data.IndicatorName; 
                endItem.LocationName = item.Key.Item3;
                endItem.Year = item.Key.Item1.ToString();
                endItem.Month = item.Key.Item2.ToString();
                endItem.GroupingName = data.GroupingName; 
                endItem.Numerator = 0;
                endItem.Denominator = item.Value.TotalHours;
            }
        }
    }
    return ListOfResults;
}

The error occurs here: 这里发生错误:

 Denominator = mergedDict[Tuple.Create(groupItem.Key.Year, groupItem.Key.Month, groupItem.Key.LocationName)].TotalHours,  

I do not understand why it is not present in the key. 我不明白为什么钥匙不存在。 The key consists on an int, int, string (year, month, location) and that is what I have assigned it. 键由int,int,string(年,月,位置)组成,这就是我分配的内容。

I've looked at all of the other threads concerning this error message but I didn't see anything that applied to my situation. 我查看了有关此错误消息的所有其他线程,但我没有看到任何适用于我的情况。

I was unsure of what tags to put on this but from my understanding the dictionary was created with linq to xml, the query is linq to sql and it's all part of C# so I used all the tags. 我不确定要用什么标签,但从我的理解,字典是用linq到xml创建的,查询是linq到sql,它是C#的所有部分所以我使用了所有的标签。 if this was incorrect then I apologize in advance. 如果这不正确,那么我提前道歉。

The problem is with comparisons between the keys you are storing in the Dictionary and the keys you are trying to look up. 问题在于您在Dictionary中存储的键与您尝试查找的键之间的比较。

When you add something to a Dictionary or access the indexer of a Dictionary it uses the GetHashCode() method to get a hash value of the key. 当您添加的东西到Dictionary或访问的索引Dictionary它使用GetHashCode()方法来获得关键的哈希值。 The hashcode for a Tuple is unique to that instance of the Tuple . 一个哈希码Tuple是唯一的该实例的Tuple This means that unless you are passing in the exact same instance of the Tuple class into the indexer, it will not find the previously stored value. 这意味着除非您将完全相同的Tuple类实例传入索引器,否则它将找不到先前存储的值。 Your usage of mergedDict[Tuple.Create(... creates a brand new Tuple with a different hash code than is stored in the Dictionary . 您对mergedDict[Tuple.Create(...创建了一个全新的元组,其散列码与存储在Dictionary中的散列码不同。

I would recommend creating your own class to use as the key and implementing GetHashCode() and the Equality methods on that class. 我建议创建自己的类作为键,并在该类上实现GetHashCode()和Equality方法。 That way the Dictionary will be able to find what you previously stored there. 通过这种方式,词典将能够找到您之前存储的内容。

More: The reason this is confusing to a lot of people is that for something like String or Int32 , String.GetHashCode() will return the same hash code for two different instances that have the same value. 更多:这让很多人感到困惑的原因是,对于像StringInt32这样的东西, String.GetHashCode()将为两个具有相同值的不同实例返回相同的哈希码。 A more specialized class such as Tuple doesn't always work the same. Tuple这样更专业的类并不总是一样。 The implementor of Tuple could have gotten the hash code of each input to the Tuple and added them together (or something), but running Tuple through a decompiler you can see that this is not the case. Tuple的实现者可以获得每个输入到Tuple的哈希码并将它们加在一起(或者其他东西),但是通过反编译器运行Tuple可以看出情况并非如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 System.Collections.Generic.KeyNotFoundException:字典中不存在给定的键“Item” - System.Collections.Generic.KeyNotFoundException : The given key 'Item' was not present in the dictionary System.Collections.Generic.KeyNotFoundException:字典中不存在给定键“All” - System.Collections.Generic.KeyNotFoundException: The given key 'All' was not present in the dictionary System.Collections.Generic.KeyNotFoundException:从PUSHSHARP发送推送通知时,字典中不存在给定的键 - System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary while sending Push Notifiaction from PUSHSHARP System.Collections.Generic.KeyNotFoundException: &#39;字典中不存在给定的键。&#39; C# 窗口应用程序 - System.Collections.Generic.KeyNotFoundException: 'The given key was not present in the dictionary.' C# windows application 没有 System.Collections.Generic.KeyNotFoundException 的字典键操作 - Operations over dictionary-key without System.Collections.Generic.KeyNotFoundException System.Collections.Generic.KeyNotFoundException似乎没有原因 - System.Collections.Generic.KeyNotFoundException For Seemingly No Reason Windows Phone中的System.Collections.Generic.KeyNotFoundException - System.Collections.Generic.KeyNotFoundException in Windows Phone Facebook MVC应用程序演示中的System.Collections.Generic.KeyNotFoundException - System.Collections.Generic.KeyNotFoundException on Facebook MVC Application demo "为什么 LINQ Sum() 抛出“System.Collections.Generic.KeyNotFoundException”?" - Why LINQ Sum() throws "System.Collections.Generic.KeyNotFoundException"? 您能解释一下此System.Collections.Generic.KeyNotFoundException吗? - Can you explain this System.Collections.Generic.KeyNotFoundException?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM