Sortedset不使用自定义等号

时间:2014-06-14 13:20:50

标签: c# ienumerable icomparable

我的类实现了IEquatable和IComparable。然后将其添加到sortedset。

目标是按“Date”属性对其进行排序,如果“ID1”和“ID2”相同,则相等。

实施的方法:

public int CompareTo(MyClass other)
{
    return other.Date.CompareTo(Date);
}

public override int GetHashCode()
{
    unchecked
    {
        var hashCode = ID1;
        hashCode = (hashCode * 397) ^ ID2;
        return hashCode;
    }
}

public bool Equals(MyClass other)
{
    if (ReferenceEquals(null, other)) 
       return false;

    if (ReferenceEquals(this, other)) 
       return true;

    return ID1 == other.ID1
        && ID2 == other.ID2;
}

生成的sortedset已正确排序,但仍有一些元素应该相等,因此不在集合中。使用断点似乎既不调用GetHashCode也不调用Equals。

有关如何解决此问题的任何提示?

1 个答案:

答案 0 :(得分:1)

SortedSet使用CompareTo进行排序和相等比较。

没有内置的有序集合,它允许您指定一种不同的方法来比较排序中的相等性,而不是比较保持清晰度的相等性。我不完全确定为什么会这样,但它可能与用于排序的算法背后的假设有关。

如果您想要这种行为,可能最简单的方法是将底层集合包装在自己的类中,这将在向集合中添加新项目之前检查清晰度。

您还需要注意,通过Equals方法排序相同但不相等的项目都可以添加到基础集合中。在您的情况下,排序由Date完成,相等性由ID1ID2完成,这可能类似于:

public int CompareTo(MyClass other)
{
    var result = other.Date.CompareTo(Date);
    if(result != 0)
        return result;
    result = other.ID1.CompareTo(ID1);
    if(result != 0)
        return result;
    return other.ID2.CompareTo(ID2);
}

如果日期相同,则会额外订购,但我不希望这是一个问题。

或者,您可以通过在排序位置强制等于比较的项目来欺骗"欺骗"这可能最好转移到自定义IComparer,因为它不是您想要的正常排序行为,在SortedSet之外:

public int CompareTo(MyClass other)
{
    if(other.Equals(this))
        return 0;

    var result = other.Date.CompareTo(Date);
    if(result != 0)
        return result;
    result = other.ID1.CompareTo(ID1);
    if(result != 0)
        return result;
    return other.ID2.CompareTo(ID2);
}

这样可以避免在集合周围创建自己的包装类,并且更安全。不过,这很酷。