diff --git a/src/mscorlib/shared/System/Collections/Generic/Dictionary.cs b/src/mscorlib/shared/System/Collections/Generic/Dictionary.cs index 8792119c0460..09434e6f54b2 100644 --- a/src/mscorlib/shared/System/Collections/Generic/Dictionary.cs +++ b/src/mscorlib/shared/System/Collections/Generic/Dictionary.cs @@ -72,10 +72,14 @@ public Dictionary(int capacity, IEqualityComparer comparer) { if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity); if (capacity > 0) Initialize(capacity); - this.comparer = comparer ?? EqualityComparer.Default; + if (comparer != EqualityComparer.Default) + { + this.comparer = comparer; + } - if (this.comparer == EqualityComparer.Default) + if (typeof(TKey) == typeof(string) && comparer == null) { + // To start, move off default comparer for string which is randomised this.comparer = (IEqualityComparer)NonRandomizedStringEqualityComparer.Default; } } @@ -139,13 +143,7 @@ protected Dictionary(SerializationInfo info, StreamingContext context) HashHelpers.SerializationInfoTable.Add(this, info); } - public IEqualityComparer Comparer - { - get - { - return comparer; - } - } + public IEqualityComparer Comparer => comparer ?? EqualityComparer.Default; public int Count { @@ -283,10 +281,9 @@ public bool ContainsValue(TValue value) } else { - EqualityComparer c = EqualityComparer.Default; for (int i = 0; i < count; i++) { - if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true; + if (entries[i].hashCode >= 0 && (default(TValue) == null ? value.Equals(entries[i].value) : EqualityComparer.Default.Equals(entries[i].value, value))) return true; } } return false; @@ -338,7 +335,7 @@ public virtual void GetObjectData(SerializationInfo info, StreamingContext conte } info.AddValue(VersionName, version); - info.AddValue(ComparerName, comparer, typeof(IEqualityComparer)); + info.AddValue(ComparerName, comparer ?? EqualityComparer.Default, typeof(IEqualityComparer)); info.AddValue(HashSizeName, buckets == null ? 0 : buckets.Length); // This is the length of the bucket array if (buckets != null) @@ -358,10 +355,10 @@ private int FindEntry(TKey key) if (buckets != null) { - int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; + int hashCode = (comparer != null ? comparer.GetHashCode(key) : key.GetHashCode()) & 0x7FFFFFFF; for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) { - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i; + if (entries[i].hashCode == hashCode && (comparer != null ? comparer.Equals(entries[i].key, key) : (default(TKey) == null ? key.Equals(entries[i].key) : EqualityComparer.Default.Equals(entries[i].key, key)))) return i; } } return -1; @@ -384,13 +381,13 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) } if (buckets == null) Initialize(0); - int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; + int hashCode = (comparer != null ? comparer.GetHashCode(key) : key.GetHashCode()) & 0x7FFFFFFF; int targetBucket = hashCode % buckets.Length; int collisionCount = 0; for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) { - if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) + if (entries[i].hashCode == hashCode && (comparer != null ? comparer.Equals(entries[i].key, key) : (default(TKey) == null ? key.Equals(entries[i].key) : EqualityComparer.Default.Equals(entries[i].key, key)))) { if (behavior == InsertionBehavior.OverwriteExisting) { @@ -437,9 +434,9 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) // If we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing // i.e. EqualityComparer.Default. - if (collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) + if (default(TKey) == null && collisionCount > HashHelpers.HashCollisionThreshold && comparer is NonRandomizedStringEqualityComparer) { - comparer = (IEqualityComparer)EqualityComparer.Default; + comparer = null; Resize(entries.Length, true); } @@ -514,7 +511,7 @@ private void Resize(int newSize, bool forceNewHashCodes) { if (newEntries[i].hashCode != -1) { - newEntries[i].hashCode = (comparer.GetHashCode(newEntries[i].key) & 0x7FFFFFFF); + newEntries[i].hashCode = (comparer != null ? comparer.GetHashCode(newEntries[i].key) : newEntries[i].key.GetHashCode()) & 0x7FFFFFFF; } } } @@ -545,7 +542,7 @@ public bool Remove(TKey key) if (buckets != null) { - int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; + int hashCode = (comparer != null ? comparer.GetHashCode(key) : key.GetHashCode()) & 0x7FFFFFFF; int bucket = hashCode % buckets.Length; int last = -1; int i = buckets[bucket]; @@ -553,7 +550,7 @@ public bool Remove(TKey key) { ref Entry entry = ref entries[i]; - if (entry.hashCode == hashCode && comparer.Equals(entry.key, key)) + if (entry.hashCode == hashCode && (comparer != null ? comparer.Equals(entry.key, key) : (default(TKey) == null ? key.Equals(entry.key) : EqualityComparer.Default.Equals(entry.key, key)))) { if (last < 0) { @@ -599,7 +596,7 @@ public bool Remove(TKey key, out TValue value) if (buckets != null) { - int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF; + int hashCode = (comparer != null ? comparer.GetHashCode(key) : key.GetHashCode()) & 0x7FFFFFFF; int bucket = hashCode % buckets.Length; int last = -1; int i = buckets[bucket]; @@ -607,7 +604,7 @@ public bool Remove(TKey key, out TValue value) { ref Entry entry = ref entries[i]; - if (entry.hashCode == hashCode && comparer.Equals(entry.key, key)) + if (entry.hashCode == hashCode && (comparer != null ? comparer.Equals(entry.key, key) : (default(TKey) == null ? key.Equals(entry.key) : EqualityComparer.Default.Equals(entry.key, key)))) { if (last < 0) {