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;
}
这是错误还是功能?
如果我们检查 SortedSet
的 reference 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()
即可完成排序。
我将用户 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
:
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
的 reference 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()
即可完成排序。