@@ -157,37 +157,54 @@ public IEqualityComparer GetEqualityComparer()
157
157
/// <returns>A hash collision resistant equality comparer.</returns>
158
158
protected virtual IEqualityComparer < T > GetHashCollisionResistantEqualityComparer < T > ( )
159
159
{
160
- // For anything 32-bits and under, our fallback base secure hasher is usually adequate since it makes the hash unpredictable.
161
- // We should have special implementations for any value that is larger than 32-bits in order to make sure
162
- // that all the data gets hashed securely rather than trivially and predictably compressed into 32-bits before being hashed.
163
- // We also have to specially handle some 32-bit types (e.g. float) where multiple in-memory representations should hash to the same value.
164
- // Any type supported by the PrimitiveObjectFormatter should be added here if supporting it as a key in a collection makes sense.
165
- return
166
- // 32-bits or smaller:
167
- typeof ( T ) == typeof ( bool ) ? CollisionResistantHasher < T > . Instance :
168
- typeof ( T ) == typeof ( char ) ? CollisionResistantHasher < T > . Instance :
169
- typeof ( T ) == typeof ( sbyte ) ? CollisionResistantHasher < T > . Instance :
170
- typeof ( T ) == typeof ( byte ) ? CollisionResistantHasher < T > . Instance :
171
- typeof ( T ) == typeof ( short ) ? CollisionResistantHasher < T > . Instance :
172
- typeof ( T ) == typeof ( ushort ) ? CollisionResistantHasher < T > . Instance :
173
- typeof ( T ) == typeof ( int ) ? CollisionResistantHasher < T > . Instance :
174
- typeof ( T ) == typeof ( uint ) ? CollisionResistantHasher < T > . Instance :
175
-
176
- // Larger than 32-bits (or otherwise require special handling):
177
- typeof ( T ) == typeof ( long ) ? ( IEqualityComparer < T > ) Int64EqualityComparer . Instance :
178
- typeof ( T ) == typeof ( ulong ) ? ( IEqualityComparer < T > ) UInt64EqualityComparer . Instance :
179
- typeof ( T ) == typeof ( float ) ? ( IEqualityComparer < T > ) SingleEqualityComparer . Instance :
180
- typeof ( T ) == typeof ( double ) ? ( IEqualityComparer < T > ) DoubleEqualityComparer . Instance :
181
- typeof ( T ) == typeof ( string ) ? ( IEqualityComparer < T > ) StringEqualityComparer . Instance :
182
- typeof ( T ) == typeof ( Guid ) ? ( IEqualityComparer < T > ) GuidEqualityComparer . Instance :
183
- typeof ( T ) == typeof ( DateTime ) ? ( IEqualityComparer < T > ) DateTimeEqualityComparer . Instance :
184
- typeof ( T ) == typeof ( DateTimeOffset ) ? ( IEqualityComparer < T > ) DateTimeOffsetEqualityComparer . Instance :
185
- typeof ( T ) == typeof ( object ) ? ( IEqualityComparer < T > ) this . objectFallbackEqualityComparer :
186
-
187
- // Any type we don't explicitly whitelist here shouldn't be allowed to use as the key in a hash-based collection since it isn't known to be hash resistant.
188
- // This method can of course be overridden to add more hash collision resistant type support, or the deserializing party can indicate that the data is Trusted
189
- // so that this method doesn't even get called.
190
- throw new TypeAccessException ( $ "No hash-resistant equality comparer available for type: { typeof ( T ) } ") ;
160
+ IEqualityComparer < T > result = null ;
161
+ if ( typeof ( T ) . GetTypeInfo ( ) . IsEnum )
162
+ {
163
+ Type underlyingType = typeof ( T ) . GetTypeInfo ( ) . GetEnumUnderlyingType ( ) ;
164
+ result =
165
+ underlyingType == typeof ( sbyte ) ? CollisionResistantHasher < T > . Instance :
166
+ underlyingType == typeof ( byte ) ? CollisionResistantHasher < T > . Instance :
167
+ underlyingType == typeof ( short ) ? CollisionResistantHasher < T > . Instance :
168
+ underlyingType == typeof ( ushort ) ? CollisionResistantHasher < T > . Instance :
169
+ underlyingType == typeof ( int ) ? CollisionResistantHasher < T > . Instance :
170
+ underlyingType == typeof ( uint ) ? CollisionResistantHasher < T > . Instance :
171
+ null ;
172
+ }
173
+ else
174
+ {
175
+ // For anything 32-bits and under, our fallback base secure hasher is usually adequate since it makes the hash unpredictable.
176
+ // We should have special implementations for any value that is larger than 32-bits in order to make sure
177
+ // that all the data gets hashed securely rather than trivially and predictably compressed into 32-bits before being hashed.
178
+ // We also have to specially handle some 32-bit types (e.g. float) where multiple in-memory representations should hash to the same value.
179
+ // Any type supported by the PrimitiveObjectFormatter should be added here if supporting it as a key in a collection makes sense.
180
+ result =
181
+ // 32-bits or smaller:
182
+ typeof ( T ) == typeof ( bool ) ? CollisionResistantHasher < T > . Instance :
183
+ typeof ( T ) == typeof ( char ) ? CollisionResistantHasher < T > . Instance :
184
+ typeof ( T ) == typeof ( sbyte ) ? CollisionResistantHasher < T > . Instance :
185
+ typeof ( T ) == typeof ( byte ) ? CollisionResistantHasher < T > . Instance :
186
+ typeof ( T ) == typeof ( short ) ? CollisionResistantHasher < T > . Instance :
187
+ typeof ( T ) == typeof ( ushort ) ? CollisionResistantHasher < T > . Instance :
188
+ typeof ( T ) == typeof ( int ) ? CollisionResistantHasher < T > . Instance :
189
+ typeof ( T ) == typeof ( uint ) ? CollisionResistantHasher < T > . Instance :
190
+
191
+ // Larger than 32-bits (or otherwise require special handling):
192
+ typeof ( T ) == typeof ( long ) ? ( IEqualityComparer < T > ) Int64EqualityComparer . Instance :
193
+ typeof ( T ) == typeof ( ulong ) ? ( IEqualityComparer < T > ) UInt64EqualityComparer . Instance :
194
+ typeof ( T ) == typeof ( float ) ? ( IEqualityComparer < T > ) SingleEqualityComparer . Instance :
195
+ typeof ( T ) == typeof ( double ) ? ( IEqualityComparer < T > ) DoubleEqualityComparer . Instance :
196
+ typeof ( T ) == typeof ( string ) ? ( IEqualityComparer < T > ) StringEqualityComparer . Instance :
197
+ typeof ( T ) == typeof ( Guid ) ? ( IEqualityComparer < T > ) GuidEqualityComparer . Instance :
198
+ typeof ( T ) == typeof ( DateTime ) ? ( IEqualityComparer < T > ) DateTimeEqualityComparer . Instance :
199
+ typeof ( T ) == typeof ( DateTimeOffset ) ? ( IEqualityComparer < T > ) DateTimeOffsetEqualityComparer . Instance :
200
+ typeof ( T ) == typeof ( object ) ? ( IEqualityComparer < T > ) this . objectFallbackEqualityComparer :
201
+ null ;
202
+ }
203
+
204
+ // Any type we don't explicitly whitelist here shouldn't be allowed to use as the key in a hash-based collection since it isn't known to be hash resistant.
205
+ // This method can of course be overridden to add more hash collision resistant type support, or the deserializing party can indicate that the data is Trusted
206
+ // so that this method doesn't even get called.
207
+ return result ?? throw new TypeAccessException ( $ "No hash-resistant equality comparer available for type: { typeof ( T ) } ") ;
191
208
}
192
209
193
210
/// <summary>
0 commit comments