Используется IEqualityComparer<T>
(EqualityComparer<T>.Default
, если вы не укажете другой в строительстве).
Когда вы добавляете элемент в набор, он найдет хеш-код, используя IEqualityComparer<T>.GetHashCode
, и сохранит как хеш-код, так и элемент (конечно, после проверки, есть ли элемент в наборе).
Чтобы найти элемент вверх, он сначала использует IEqualityComparer<T>.GetHashCode
, чтобы найти хеш-код, затем для всех элементов с одинаковым хеш-кодом, он будет использовать IEqualityComparer<T>.Equals
для сравнения на фактическое равенство.
Это означает, что у вас есть два варианта:
- Передайте пользовательский
IEqualityComparer<T>
в конструктор. Это лучший вариант, если вы не можете изменить сам T
или если вы хотите установить отношение равенства не по умолчанию (например, «все пользователи с отрицательным идентификатором пользователя считаются равными»). Это почти никогда не реализовано в самом типе (то есть 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
.