My class implements IEquatable and IComparable. It then gets added to a sortedset.
The goal is to have it be sorted by its "Date" property and be equal if both "ID1" and "ID2" are the same.
The implemented methods:
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;
}
The resulting sortedset is correctly sorted, but there are still elements that should be equal and therefore not in the set. Using breakpoints it seems neither GetHashCode nor Equals get called.
Any tips on how to solve this?
SortedSet
usesCompareTo
for both sorting and equality comparison.There isn't an in-built ordered collection which will allow you to specify a different method to compare for equality in ordering than to compare for equality in maintaining distinctness. I'm not completely sure why this is, but it may be to do with the asssumptions behind the algorithms used for sorting.
If you want this behaviour, probably the simplest way to do it is wrap the underlying collection in its own class which will check for distinctness before adding new items to the collection.
You also need to be careful that items which are equal for sorting but not equal by your
Equals
method can both be added to the underlying collection. In your case, where the sorting is done byDate
and the equality is done byID1
andID2
this might look something like:This imposes extra ordering if the dates are the same, but I wouldn't expect that to be a problem.
Alternatively, you can "cheat", by forcing items which are equal to compare as equal in sort position. This would probably best be moved to a custom
IComparer
, because it's not the normal sorting behaviour you want, outside aSortedSet
:This would allow you to avoid having to create your own wrapper class around the collection, and is safer. It is rather hacky, though.