From c86bb5f86a160699645e78f46a2921640adc6787 Mon Sep 17 00:00:00 2001 From: Matous Kozak Date: Thu, 11 Jul 2024 09:05:57 +0200 Subject: [PATCH] Revert "Improve fast-return for HashSet SubSet and SetEquals methods (#102758)" This reverts commit f6d12a1dcf162b05ebd61900d9ebf81ebf58a38f. --- .../src/System/Collections/Generic/HashSet.cs | 74 +++++++++---------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs index ba6d497a29f89..658716801fefa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/HashSet.cs @@ -879,26 +879,25 @@ public bool IsSubsetOf(IEnumerable other) } // The empty set is a subset of any set, and a set is a subset of itself. - // Set is always a subset of itself. + // Set is always a subset of itself if (Count == 0 || other == this) { return true; } - if (other is ICollection otherAsCollection) + // Faster if other has unique elements according to this equality comparer; so check + // that other is a hashset using the same equality comparer. + if (other is HashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) { - // If this has more elements then it can't be a subset. - if (Count > otherAsCollection.Count) + // if this has more elements then it can't be a subset + if (Count > otherAsSet.Count) { return false; } - // Faster if other has unique elements according to this equality comparer; so check - // that other is a hashset using the same equality comparer. - if (other is HashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) - { - return IsSubsetOfHashSetWithSameComparer(otherAsSet); - } + // already checked that we're using same equality comparer. simply check that + // each element in this is contained in other. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); } (int uniqueCount, int unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: false); @@ -923,8 +922,8 @@ public bool IsProperSubsetOf(IEnumerable other) if (other is ICollection otherAsCollection) { - // No set is a proper subset of a set with less or equal number of elements. - if (otherAsCollection.Count <= Count) + // No set is a proper subset of an empty set. + if (otherAsCollection.Count == 0) { return false; } @@ -932,13 +931,17 @@ public bool IsProperSubsetOf(IEnumerable other) // The empty set is a proper subset of anything but the empty set. if (Count == 0) { - // Based on check above, other is not empty when Count == 0. - return true; + return otherAsCollection.Count > 0; } // Faster if other is a hashset (and we're using same equality comparer). if (other is HashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) { + if (Count >= otherAsSet.Count) + { + return false; + } + // This has strictly less than number of items in other, so the following // check suffices for proper subset. return IsSubsetOfHashSetWithSameComparer(otherAsSet); @@ -1085,38 +1088,33 @@ public bool SetEquals(IEnumerable other) return true; } - if (other is ICollection otherAsCollection) + // Faster if other is a hashset and we're using same equality comparer. + if (other is HashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) { - // If this is empty, they are equal iff other is empty. - if (Count == 0) + // Attempt to return early: since both contain unique elements, if they have + // different counts, then they can't be equal. + if (Count != otherAsSet.Count) { - return otherAsCollection.Count == 0; - } - - // Faster if other is a hashset and we're using same equality comparer. - if (other is HashSet otherAsSet && EqualityComparersAreEqual(this, otherAsSet)) - { - // Attempt to return early: since both contain unique elements, if they have - // different counts, then they can't be equal. - if (Count != otherAsSet.Count) - { - return false; - } - - // Already confirmed that the sets have the same number of distinct elements, so if - // one is a subset of the other then they must be equal. - return IsSubsetOfHashSetWithSameComparer(otherAsSet); + return false; } - // Can't be equal if other set contains fewer elements than this. - if (Count > otherAsCollection.Count) + // Already confirmed that the sets have the same number of distinct elements, so if + // one is a subset of the other then they must be equal. + return IsSubsetOfHashSetWithSameComparer(otherAsSet); + } + else + { + // If this count is 0 but other contains at least one element, they can't be equal. + if (Count == 0 && + other is ICollection otherAsCollection && + otherAsCollection.Count > 0) { return false; } - } - (int uniqueCount, int unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); - return uniqueCount == Count && unfoundCount == 0; + (int uniqueCount, int unfoundCount) = CheckUniqueAndUnfoundElements(other, returnIfUnfound: true); + return uniqueCount == Count && unfoundCount == 0; + } } public void CopyTo(T[] array) => CopyTo(array, 0, Count);