summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs')
-rw-r--r--src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs171
1 files changed, 93 insertions, 78 deletions
diff --git a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
index b845d64fed..3731114119 100644
--- a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
+++ b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
@@ -32,7 +32,6 @@ namespace System.Collections.Generic
// Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen
// saves the right instantiations
//
- [System.Security.SecuritySafeCritical] // auto-generated
private static EqualityComparer<T> CreateComparer()
{
Contract.Ensures(Contract.Result<EqualityComparer<T>>() != null);
@@ -144,10 +143,7 @@ namespace System.Collections.Generic
}
[Pure]
- public override int GetHashCode(T obj) {
- if (obj == null) return 0;
- return obj.GetHashCode();
- }
+ public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0;
internal override int IndexOf(T[] array, T value, int startIndex, int count) {
int endIndex = startIndex + count;
@@ -179,22 +175,21 @@ namespace System.Collections.Generic
return -1;
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- GenericEqualityComparer<T> comparer = obj as GenericEqualityComparer<T>;
- return comparer != null;
- }
+ // Equals method for the comparer itself.
+ // If in the future this type is made sealed, change the is check to obj != null && GetType() == obj.GetType().
+ public override bool Equals(Object obj) =>
+ obj is GenericEqualityComparer<T>;
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
- }
+ // If in the future this type is made sealed, change typeof(...) to GetType().
+ public override int GetHashCode() =>
+ typeof(GenericEqualityComparer<T>).GetHashCode();
}
[Serializable]
- internal class NullableEqualityComparer<T> : EqualityComparer<Nullable<T>> where T : struct, IEquatable<T>
+ internal sealed class NullableEqualityComparer<T> : EqualityComparer<T?> where T : struct, IEquatable<T>
{
[Pure]
- public override bool Equals(Nullable<T> x, Nullable<T> y) {
+ public override bool Equals(T? x, T? y) {
if (x.HasValue) {
if (y.HasValue) return x.value.Equals(y.value);
return false;
@@ -204,11 +199,9 @@ namespace System.Collections.Generic
}
[Pure]
- public override int GetHashCode(Nullable<T> obj) {
- return obj.GetHashCode();
- }
+ public override int GetHashCode(T? obj) => obj.GetHashCode();
- internal override int IndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count) {
+ internal override int IndexOf(T?[] array, T? value, int startIndex, int count) {
int endIndex = startIndex + count;
if (!value.HasValue) {
for (int i = startIndex; i < endIndex; i++) {
@@ -223,7 +216,7 @@ namespace System.Collections.Generic
return -1;
}
- internal override int LastIndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count) {
+ internal override int LastIndexOf(T?[] array, T? value, int startIndex, int count) {
int endIndex = startIndex - count + 1;
if (!value.HasValue) {
for (int i = startIndex; i >= endIndex; i--) {
@@ -238,19 +231,16 @@ namespace System.Collections.Generic
return -1;
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- NullableEqualityComparer<T> comparer = obj as NullableEqualityComparer<T>;
- return comparer != null;
- }
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
- }
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
}
[Serializable]
- internal class ObjectEqualityComparer<T>: EqualityComparer<T>
+ internal sealed class ObjectEqualityComparer<T>: EqualityComparer<T>
{
[Pure]
public override bool Equals(T x, T y) {
@@ -263,10 +253,7 @@ namespace System.Collections.Generic
}
[Pure]
- public override int GetHashCode(T obj) {
- if (obj == null) return 0;
- return obj.GetHashCode();
- }
+ public override int GetHashCode(T obj) => obj?.GetHashCode() ?? 0;
internal override int IndexOf(T[] array, T value, int startIndex, int count) {
int endIndex = startIndex + count;
@@ -298,25 +285,21 @@ namespace System.Collections.Generic
return -1;
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- ObjectEqualityComparer<T> comparer = obj as ObjectEqualityComparer<T>;
- return comparer != null;
- }
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
- }
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
}
-#if FEATURE_CORECLR
// NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...>
// As the randomized string hashing is turned on by default on coreclr, we need to keep the performance not affected
// as much as possible in the main stream scenarios like Dictionary<string,>
// We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which
// keep the perofrmance not affected till we hit collision threshold and then we switch to the comparer which is using
// randomized string hashing GenericEqualityComparer<string>
-
+ [Serializable]
internal class NonRandomizedStringEqualityComparer : GenericEqualityComparer<string> {
static IEqualityComparer<string> s_nonRandomizedComparer;
@@ -335,12 +318,11 @@ namespace System.Collections.Generic
return obj.GetLegacyNonRandomizedHashCode();
}
}
-#endif // FEATURE_CORECLR
// Performance of IndexOf on byte array is very important for some scenarios.
// We will call the C runtime function memchr, which is optimized.
[Serializable]
- internal class ByteEqualityComparer: EqualityComparer<byte>
+ internal sealed class ByteEqualityComparer: EqualityComparer<byte>
{
[Pure]
public override bool Equals(byte x, byte y) {
@@ -352,14 +334,13 @@ namespace System.Collections.Generic
return b.GetHashCode();
}
- [System.Security.SecuritySafeCritical] // auto-generated
internal unsafe override int IndexOf(byte[] array, byte value, int startIndex, int count) {
if (array==null)
- throw new ArgumentNullException("array");
+ throw new ArgumentNullException(nameof(array));
if (startIndex < 0)
- throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ throw new ArgumentOutOfRangeException(nameof(startIndex), Environment.GetResourceString("ArgumentOutOfRange_Index"));
if (count < 0)
- throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_Count"));
if (count > array.Length - startIndex)
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
Contract.EndContractBlock();
@@ -377,15 +358,12 @@ namespace System.Collections.Generic
return -1;
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- ByteEqualityComparer comparer = obj as ByteEqualityComparer;
- return comparer != null;
- }
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
- }
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
}
[Serializable]
@@ -409,7 +387,6 @@ namespace System.Collections.Generic
// This is used by the serialization engine.
protected EnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
- [SecurityCritical]
public void GetObjectData(SerializationInfo info, StreamingContext context) {
// For back-compat we need to serialize the comparers for enums with underlying types other than int as ObjectEqualityComparer
if (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))) != TypeCode.Int32) {
@@ -417,14 +394,35 @@ namespace System.Collections.Generic
}
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- EnumEqualityComparer<T> comparer = obj as EnumEqualityComparer<T>;
- return comparer != null;
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+
+ internal override int IndexOf(T[] array, T value, int startIndex, int count)
+ {
+ int toFind = JitHelpers.UnsafeEnumCast(value);
+ int endIndex = startIndex + count;
+ for (int i = startIndex; i < endIndex; i++)
+ {
+ int current = JitHelpers.UnsafeEnumCast(array[i]);
+ if (toFind == current) return i;
+ }
+ return -1;
}
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
+ internal override int LastIndexOf(T[] array, T value, int startIndex, int count)
+ {
+ int toFind = JitHelpers.UnsafeEnumCast(value);
+ int endIndex = startIndex - count + 1;
+ for (int i = startIndex; i >= endIndex; i--)
+ {
+ int current = JitHelpers.UnsafeEnumCast(array[i]);
+ if (toFind == current) return i;
+ }
+ return -1;
}
}
@@ -474,28 +472,48 @@ namespace System.Collections.Generic
return x_final.GetHashCode();
}
- // Equals method for the comparer itself.
- public override bool Equals(Object obj){
- LongEnumEqualityComparer<T> comparer = obj as LongEnumEqualityComparer<T>;
- return comparer != null;
- }
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
- public override int GetHashCode() {
- return this.GetType().Name.GetHashCode();
- }
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
public LongEnumEqualityComparer() { }
// This is used by the serialization engine.
public LongEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
- [SecurityCritical]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
// The LongEnumEqualityComparer does not exist on 4.0 so we need to serialize this comparer as ObjectEqualityComparer
// to allow for roundtrip between 4.0 and 4.5.
info.SetType(typeof(ObjectEqualityComparer<T>));
}
+
+ internal override int IndexOf(T[] array, T value, int startIndex, int count)
+ {
+ long toFind = JitHelpers.UnsafeEnumCastLong(value);
+ int endIndex = startIndex + count;
+ for (int i = startIndex; i < endIndex; i++)
+ {
+ long current = JitHelpers.UnsafeEnumCastLong(array[i]);
+ if (toFind == current) return i;
+ }
+ return -1;
+ }
+
+ internal override int LastIndexOf(T[] array, T value, int startIndex, int count)
+ {
+ long toFind = JitHelpers.UnsafeEnumCastLong(value);
+ int endIndex = startIndex - count + 1;
+ for (int i = startIndex; i >= endIndex; i--)
+ {
+ long current = JitHelpers.UnsafeEnumCastLong(array[i]);
+ if (toFind == current) return i;
+ }
+ return -1;
+ }
}
#if FEATURE_RANDOMIZED_STRING_HASHING
@@ -528,14 +546,12 @@ namespace System.Collections.Generic
}
[Pure]
- [SecuritySafeCritical]
public int GetHashCode(String obj) {
if(obj == null) return 0;
return String.InternalMarvin32HashString(obj, obj.Length, _entropy);
}
[Pure]
- [SecuritySafeCritical]
public int GetHashCode(Object obj) {
if(obj == null) return 0;
@@ -552,7 +568,7 @@ namespace System.Collections.Generic
}
public override int GetHashCode() {
- return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
+ return (this.GetType().GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
}
@@ -587,7 +603,6 @@ namespace System.Collections.Generic
}
[Pure]
- [SecuritySafeCritical]
public int GetHashCode(Object obj) {
if(obj == null) return 0;
@@ -604,7 +619,7 @@ namespace System.Collections.Generic
}
public override int GetHashCode() {
- return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
+ return (this.GetType().GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
}
IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {