@@ -69,7 +69,7 @@ public HashSet(IEqualityComparer<T>? comparer)
6969 // We use a non-randomized comparer for improved perf, falling back to a randomized comparer if the
7070 // hash buckets become unbalanced.
7171 if ( typeof ( T ) == typeof ( string ) &&
72- NonRandomizedStringEqualityComparer . GetStringComparer ( _comparer ! ) is IEqualityComparer < string > stringComparer )
72+ NonRandomizedStringEqualityComparer . GetStringComparer ( _comparer ) is IEqualityComparer < string > stringComparer )
7373 {
7474 _comparer = ( IEqualityComparer < T > ) stringComparer ;
7575 }
@@ -92,7 +92,7 @@ public HashSet(IEnumerable<T> collection, IEqualityComparer<T>? comparer) : this
9292 ThrowHelper . ThrowArgumentNullException ( ExceptionArgument . collection ) ;
9393 }
9494
95- if ( collection is HashSet < T > otherAsHashSet && EqualityComparersAreEqual ( this , otherAsHashSet ) )
95+ if ( collection is HashSet < T > otherAsHashSet && EffectiveEqualityComparersAreEqual ( this , otherAsHashSet ) )
9696 {
9797 ConstructFrom ( otherAsHashSet ) ;
9898 }
@@ -145,6 +145,8 @@ protected HashSet(SerializationInfo info, StreamingContext context)
145145 /// <summary>Initializes the HashSet from another HashSet with the same element type and equality comparer.</summary>
146146 private void ConstructFrom ( HashSet < T > source )
147147 {
148+ Debug . Assert ( EffectiveEqualityComparersAreEqual ( this , source ) , "must use identical effective comparers." ) ;
149+
148150 if ( source . Count == 0 )
149151 {
150152 // As well as short-circuiting on the rest of the work done,
@@ -1250,6 +1252,11 @@ public IEqualityComparer<T> Comparer
12501252 }
12511253 }
12521254
1255+ /// <summary>
1256+ /// Similar to <see cref="Comparer"/> but surfaces the actual comparer being used to hash entries.
1257+ /// </summary>
1258+ internal IEqualityComparer < T > EffectiveComparer => _comparer ?? EqualityComparer < T > . Default ;
1259+
12531260 /// <summary>Ensures that this hash set can hold the specified number of elements without growing.</summary>
12541261 public int EnsureCapacity ( int capacity )
12551262 {
@@ -1768,7 +1775,13 @@ private unsafe void SymmetricExceptWithEnumerable(IEnumerable<T> other)
17681775 /// </summary>
17691776 internal static bool EqualityComparersAreEqual ( HashSet < T > set1 , HashSet < T > set2 ) => set1 . Comparer . Equals ( set2 . Comparer ) ;
17701777
1771- #endregion
1778+ /// <summary>
1779+ /// Checks if effective equality comparers are equal. This is used for algorithms that
1780+ /// require that both collections use identical hashing implementations for their entries.
1781+ /// </summary>
1782+ internal static bool EffectiveEqualityComparersAreEqual ( HashSet < T > set1 , HashSet < T > set2 ) => set1 . EffectiveComparer . Equals ( set2 . EffectiveComparer ) ;
1783+
1784+ #endregion
17721785
17731786 private struct Entry
17741787 {
0 commit comments