简体   繁体   English

“词典中不存在给定的键”-但这是

[英]“The given key was not present in the dictionary” - But it is

So this seems like a problem that comes up a reasonable amount (Based on questions with the same title), but i'm stumped by my occurrence. 因此,这似乎是一个相当数量的问题(基于具有相同标题的问题),但是我为自己的出现而感到困惑。 I have inherited code, and I'm really confused by an error I'm getting 我已经继承了代码,但我对收到的错误感到非常困惑

I have an object 我有一个对象

FiscalSamplingPoint currentPoint

pretty basic definition 相当基本的定义

public sealed class FiscalSamplingPoint : SamplingPoint, IComparable<FiscalSamplingPoint>, IEquatable<FiscalSamplingPoint>
{
    private readonly int _fiscalYear;
    private readonly int _periodNumber;
    private readonly FiscalPeriodType _periodType;

...
}

FiscalPeriodType is an enum FiscalPeriodType是一个枚举

I have a SortedList (unsure why they are using it as a dictionary) "absolutes" of key FiscalSamplingPoint. 我有一个关键FiscalSamplingPoint的SortedList(不确定为什么将其用作字典)。

SortedList<FiscalSamplingPoint, PeriodsRepositoryRange>

on a specific currentPoint it throws the given key not present exception, and as excepted, 在特定的currentPoint上,它抛出给定的密钥不存在异常,并且作为例外,

absolutes.containsKey(currentPoint) 

is false (visual studio 2010 watch debugger) 为假(Visual Studio 2010监视调试器)

However, we have overriden GetHashCode and Equals. 但是,我们已覆盖GetHashCode和Equals。

and again using visual studio's watch debugger I do 并再次使用Visual Studio的手表调试器

currentPoint.GetHashCode 

and

(new System.Collections.Generic.System_DictionaryDebugView<TR.API.Common.FiscalSamplingPoint,TR.API.Common.PeriodsRepositoryRange>(absolutes)).Items[3].Key.GetHashCode()

and both return the same result (62234 to be exact) 两者都返回相同的结果(准确地说是62234)

and

currentPoint.Equals((new System.Collections.Generic.System_DictionaryDebugView<TR.API.Common.FiscalSamplingPoint,TR.API.Common.PeriodsRepositoryRange>(absolutes)).Items[3].Key)

returns true. 返回true。

I really have no clue at this point what could be the issue. 目前我真的不知道可能是什么问题。 any pointers would be appreciated. 任何指针,将不胜感激。

edit: here are relevant functions 编辑:这是相关功能

public bool Equals(FiscalSamplingPoint obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    return InternalEquals(obj);
}

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != typeof (FiscalSamplingPoint)) return false;
        return InternalEquals((FiscalSamplingPoint) obj);
}

private bool InternalEquals(FiscalSamplingPoint obj)
{
    return _fiscalYear == obj.FiscalYear && _periodNumber == obj.PeriodNumber && _periodType == obj.PeriodType;
}

public override int GetHashCode()
{
    return 31*_fiscalYear + 53*_periodNumber + 13*(int) _periodType;
}

For IComparable we have a few functions that work together 对于IComparable,我们有一些功能可以一起使用

    public int CompareTo(FiscalSamplingPoint other)
    {
        if (other == null)
        {
            throw new ApplicationException("Other object is null");
        }

        if (this > other)
        {
            return 1;
        }
        if (Equals(other))
        {
            return 0;
        }
        return -1;
    }

    public static bool operator <(FiscalSamplingPoint point1, FiscalSamplingPoint point2)
    {
        if (point1._periodType < point2._periodType)
            return true;

        if (point1._fiscalYear < point2._fiscalYear)
            return true;

        if (point1._fiscalYear == point2._fiscalYear)
            return point1.PeriodNumber < point2.PeriodNumber;

        return false;
    }

    public static bool operator >(FiscalSamplingPoint point1, FiscalSamplingPoint point2)
    {
        if (point1._periodType > point2._periodType)
            return true;

        if (point1._fiscalYear > point2._fiscalYear)
        {
            return true;
        }
        if (point1._fiscalYear == point2._fiscalYear)
        {
            return point1.PeriodNumber > point2.PeriodNumber;
        }

        return false;
    }

Implementation of < and > operators is the reason that the absolutes.containsKey(currentPoint) returns false even when the key is present in the list. <>运算符的实现是即使列表中存在键, absolutes.containsKey(currentPoint)也会返回false的原因。 SordedList<T,K> uses BinarySearch to look for the key in the list, but can't find it because the list is not sorted properly. SordedList<T,K>使用BinarySearch在列表中查找键,但由于列表未正确排序而无法找到它。

Most likely the Enum values play a major role to incorrect comparison. 枚举值很可能在不正确的比较中起主要作用。 Their numerical value is greater than, even thought the contextual meaning might be less. 它们的数值大于,甚至认为上下文含义可能会较小。

I suspect the you can change the < and > operators to something like what Will is suggesting in his answer. 我怀疑您可以将<>运算符更改为类似于Will在其答案中建议的内容。

The fault lies in implementation of the < and > operators, which return incorrect true/false values at times. 错误在于<和>运算符的实现,有时会返回错误的true / false值。 They're not needed if CompareTo is implemented as below. 如果CompareTo实现如下,则不需要它们。

ps. PS。 Swap the Type, Year and Period order around if you need to sort in a different order. 如果需要按其他顺序排序,请交换“类型”,“年”和“期间”顺序。

public int CompareTo(FiscalSamplingPoint point)
{
    if (point == null)
        return 1;

    if (this._periodType != point._periodType)
        return this._periodType < point._periodType? -1 : 1;

    if (this._fiscalYear != point._fiscalYear)
        return this._fiscalYear < point._fiscalYear? -1 : 1;

    if (this._periodNumber != point._periodNumber)
        return this._periodNumber < point._periodNumber? -1 : 1;

    return 0;
}

NB I'd also use CompareTo for the Equals implementation to avoid duplicating code. 注意我也将CompareTo用于Equals实现,以避免重复代码。 eg. 例如。

point1.CompareTo(point2) == 0

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM