Sortedset没有使用自定义等号

本文关键字:自定义 Sortedset | 更新日期: 2023-09-27 18:08:32

我的类实现了IEquatable和IComparable。然后它被添加到一个排序集。

的目标是让它按照"日期"属性排序,如果"ID1"answers"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。

对于如何解决这个问题有什么建议吗?

Sortedset没有使用自定义等号

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

这将允许您避免在集合周围创建自己的包装器类,并且更安全。