Sortedset不使用自定义等于 [英] Sortedset not using custom equals

查看:95
本文介绍了Sortedset不使用自定义等于的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的课程实现了IEquatable和IComparable.然后将其添加到sortedset.

My class implements IEquatable and IComparable. It then gets added to a sortedset.

目标是让其按其日期"属性排序,并且如果"ID1"和"ID2"相同,则相等.

The goal is to have it be sorted by its "Date" property and be equal if both "ID1" and "ID2" are the same.

已实现的方法:

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.

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使用CompareTo进行排序和相等性比较.

SortedSet uses CompareTo 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.

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

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 by Date and the equality is done by ID1 and ID2 this might look something like:

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

如果日期相同,这会强加额外的顺序,但是我不希望这是个问题.

This imposes extra ordering if the dates are the same, but I wouldn't expect that to be a problem.

或者,您可以通过强制相等的项目在排序位置进行比较来欺骗".最好将其移到自定义IComparer上,因为这不是您想要的常规排序行为,在SortedSet之外:

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

这将使您避免在集合周围创建自己的包装器类,并且更加安全.不过,它很hacky.

This would allow you to avoid having to create your own wrapper class around the collection, and is safer. It is rather hacky, though.

这篇关于Sortedset不使用自定义等于的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆