我的类实现了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。
有关如何解决此问题的任何提示?
答案 0 :(得分:1)
SortedSet
使用CompareTo
进行排序和相等比较。
没有内置的有序集合,它允许您指定一种不同的方法来比较排序中的相等性,而不是比较保持清晰度的相等性。我不完全确定为什么会这样,但它可能与用于排序的算法背后的假设有关。
如果您想要这种行为,可能最简单的方法是将底层集合包装在自己的类中,这将在向集合中添加新项目之前检查清晰度。
您还需要注意,通过Equals
方法排序相同但不相等的项目都可以添加到基础集合中。在您的情况下,排序由Date
完成,相等性由ID1
和ID2
完成,这可能类似于:
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);
}
这样可以避免在集合周围创建自己的包装类,并且更安全。不过,这很酷。