HashSet如何比较元素是否相等?

我有一堂课是IComparable

public class a : IComparable

{

public int Id { get; set; }

public string Name { get; set; }

public a(int id)

{

this.Id = id;

}

public int CompareTo(object obj)

{

return this.Id.CompareTo(((a)obj).Id);

}

}

当我将此类的对象列表添加到哈希集时:

a a1 = new a(1);

a a2 = new a(2);

HashSet<a> ha = new HashSet<a>();

ha.add(a1);

ha.add(a2);

ha.add(a1);

一切都很好,ha.count还是2,但是:

a a1 = new a(1);

a a2 = new a(2);

HashSet<a> ha = new HashSet<a>();

ha.add(a1);

ha.add(a2);

ha.add(new a(1));

现在ha.count3

  1. 为什么不HashSet尊重aCompareTo方法。
  2. HashSet拥有唯一对象列表的最佳方法是吗?

回答:

它使用一个IEqualityComparer<T>EqualityComparer<T>.Default除非您在构造上指定了另一个)。

将元素添加到集合中时,它将使用来查找哈希码IEqualityComparer<T>.GetHashCode,并存储哈希码和元素(当然,在检查元素是否已在集合中之后)。

要查找一个元素,它将首先使用IEqualityComparer<T>.GetHashCode来查找哈希码,然后对于具有相同哈希码的所有元素,它将IEqualityComparer<T>.Equals用于比较实际相等性。

这意味着您有两个选择:

  • 将自定义传递给IEqualityComparer<T>构造函数。如果您不能修改T自身,或者想要一个非默认的相等关系(例如,“所有具有负用户ID的用户都被视为相等”),则这是最佳选择。这几乎从未在类型本身上实现(即Foo未实现IEqualityComparer<Foo>),而是在单独的类型中仅用于比较。
  • 通过覆盖GetHashCode和实现类型本身的相等性Equals(object)。理想情况下,也要IEquatable<T>在类型中实现,尤其是在它是值类型时。这些方法将由默认的相等比较器调用。

请注意,从 顺序 比较的角度来看,这些都不是什么-这很有意义,因为在某些情况下,您可以轻松指定相等性但不能指定总顺序。Dictionary<TKey,

TValue>基本上与都一样。

如果要使用 排序 而不是相等比较的集合,则应SortedSet<T>从.NET 4 使用-

允许您指定一个IComparer<T>而不是一个IEqualityComparer<T>。这将使用IComparer<T>.Compare-将委派给,IComparable<T>.CompareTo或者IComparable.CompareTo如果您正在使用Comparer<T>.Default

以上是 HashSet如何比较元素是否相等? 的全部内容, 来源链接: utcz.com/qa/416905.html

回到顶部