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