“给定的密钥没有出现在字典中” - 但确实如此

时间:2013-12-12 22:42:47

标签: c#

所以这似乎是一个合理数量的问题(基于同一标题的问题),但我被我的发生所困扰。 我继承了代码,我真的很困惑,因为我得到的错误

我有一个对象

FiscalSamplingPoint currentPoint

非常基本的定义

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

...
}

FiscalPeriodType是一个枚举

我有一个SortedList(不确定为什么他们将它用作字典)关键FiscalSamplingPoint的“绝对”。

SortedList<FiscalSamplingPoint, PeriodsRepositoryRange>

在特定的currentPoint上抛出给定的密钥不存在异常,并且除外,

absolutes.containsKey(currentPoint) 

是假的(visual studio 2010 watch debugger)

但是,我们已经覆盖了GetHashCode和Equals。

再次使用visual studio的手表调试器

currentPoint.GetHashCode 

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

并且都返回相同的结果(确切地说是62234)

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

返回true。

我真的不知道这可能是什么问题。任何指针都会受到赞赏。

编辑:这里是相关功能

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

对于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;
    }

2 个答案:

答案 0 :(得分:2)

<>运算符的实现是absolutes.containsKey(currentPoint)返回false的原因,即使密钥存在于列表中也是如此。 SordedList<T,K>使用BinarySearch在列表中查找密钥,但无法找到它,因为列表未正确排序。

很可能Enum值对错误比较起主要作用。他们的数值大于,甚至认为语境意义可能更小。

我怀疑您可以将<>运营商更改为Will在其答案中提出的建议。

答案 1 :(得分:2)

错误在于&lt;和&gt;运算符,有时返回不正确的true / false值。如果CompareTo实现如下,则不需要它们。

PS。如果需要按不同的顺序排序,请交换类型,年份和期间顺序。

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

请注意,我还将CompareTo用于Equals实现,以避免重复代码。例如

point1.CompareTo(point2) == 0