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