c# CompareTo 与 SortedSets 的行为不符合预期

c# CompareTo not behaving as expected along with SortedSets

我将用户 table-列配置存储在一个简单的 class:

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

这些 classes 存储在一个 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;
            }
     }

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

MSDN 文档说:“实现 IComparable 的类型必须覆盖 Equals。覆盖 Equals 的类型也必须覆盖 GetHashCode;否则,Hashtable 可能无法正常工作。

所以,我也实现了这两个,但没有成功:

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:

的另一个结果处理不同 tables 的条目
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;
    }

这是错误还是功能?

如果我们检查 SortedSetreference source code,我们可以查看 AddIfNotPresent() 的实现。 returns 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() 方法来查看项目是否相同。因此,对于您的 class,它只关心 Position 是否相同。如果是,则不添加新项目。

我会说这是一个深思熟虑的设计 - 这不是错误。

您必须更改 CompareTo() 实现,以便它比较所有与 Equals() 相同的元素。只需调用每个元素的 CompareTo() 即可完成排序。