C#CompareTo与SortedSets行为不符

问题描述

我将用户table-column-configuration存储在一个简单类中:

public class ColumnUserSetting : IComparable<ColumnUserSetting>
        {
            public String TableWrapperName { get; set; }
            public String ColumnName { get; set; }
            public Boolean Enabled { get; set; }
            public int Width { get; set; }
            public int Position { get; set; }
        }
}

这些类存储在SortedSet中-因此,它需要实现IComparable<>,我根据位置实现了该功能,正如文档中所说的那样,它是关于位置比较的-没有什么可以说它们不能相同:

public class ColumnUserSetting : IComparable<ColumnUserSetting>
        {
            public String TableWrapperName { get; set; }
            public String ColumnName { get; set; }
            public Boolean Enabled { get; set; }
            public int Width { get; set; }
            public int Position { get; set; }

            public int Compareto(ColumnUserSetting other)
            {
                if (other.Position == this.Position) return 0;
                if (other.Position > this.Position) return -1;
                return 1;
            }
     }

但是,在同一运行中,这似乎表现为“等于”。具有相同位置的条目在集合内相互覆盖。 (即使表中的列不同)

MSDN Docu说:“ 实现IComparable的类型必须重写Equals。重写Equals的类型也必须重写GetHashCode;否则,哈希表可能无法正常工作。

因此,我也同时实现了这两个,但没有成功:

public class ColumnUserSetting : IComparable<ColumnUserSetting>
{
    public String TableWrapperName { get; set; }
    public String ColumnName { get; set; }
    public Boolean Enabled { get; set; }
    public int Width { get; set; }
    public int Position { get; set; }

    public int Compareto(ColumnUserSetting other)
    {
        if (other.Position == this.Position) return 0;
        if (other.Position > this.Position) return -1;
        return 1;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is ColumnUserSetting))
            return false;

        ColumnUserSetting cus = (ColumnUserSetting)obj;
        return (this.TableWrapperName == cus.TableWrapperName && 
                this.ColumnName == cus.TableWrapperName &&
                this.Enabled == cus.Enabled &&
                this.Width == cus.Width && 
                this.Position == cus.Position);
    }

    public override int GetHashCode()
    {
        var hashcode = 352033288;
        hashcode = hashcode * -1521134295 + TableWrapperName.GetHashCode();
        hashcode = hashcode * -1521134295 + ColumnName.GetHashCode();
        hashcode = hashcode * -1521134295 + Enabled.GetHashCode();
        hashcode = hashcode * -1521134295 + Width.GetHashCode();
        hashcode = hashcode * -1521134295 + Position.GetHashCode();
        return hashcode;
    }
}

使SortedSet正常工作的唯一方法是处理不同表的条目,并获得Compareto的另一个结果:

public int Compareto(ColumnUserSetting other)
    {
        if (this.TableWrapperName != other.TableWrapperName)
            return String.Compare(this.TableWrapperName,other.TableWrapperName);

        if (other.Position == this.Position) return 0;
        if (other.Position > this.Position) return -1;
        return 1;
    }

这是错误还是功能

解决方法

如果我们检查SortedSet的{​​{3}},我们可以看看AddIfNotPresent()的实现。如果已添加项目,则返回true,如果已存在,则返回false

方法开始附近,我们有:

int order = 0;
while (current != null) {
    order = comparer.Compare(item,current.Item);
    if (order == 0) {
        // We could have changed root node to red during the search process.
        // We need to set it to black before we return.
        root.IsRed = false;
        return false;
    }

因此,它仅调用Compare()方法来查看该项是否相同。因此,对于您的班级,它只关心Position是否相同。如果是,则不添加新项目。

我会说这是故意设计的-不是错误。

您将不得不更改您的CompareTo()实现,以便将与Equals()相同的所有元素进行比较。只需调用每个元素的CompareTo()即可完成完整的排序。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...