diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs index 4c9974fadd5b0b..55f7e7e34f2ea6 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableHashSet_1.cs @@ -743,39 +743,40 @@ private static bool SetEquals(IEnumerable other, MutationInput origin) switch (other) { case ImmutableHashSet otherAsImmutableHashSet: - if (otherAsImmutableHashSet.Count != origin.Count) - { - return false; - } - if (EqualityComparer>.Default.Equals(origin.EqualityComparer, otherAsImmutableHashSet.KeyComparer)) { + if (otherAsImmutableHashSet.Count != origin.Count) + { + return false; + } return SetEqualsWithImmutableHashset(otherAsImmutableHashSet, origin); } - break; - case HashSet otherAsHashset: - if (otherAsHashset.Count != origin.Count) + if (otherAsImmutableHashSet.Count < origin.Count) { return false; } + break; + case HashSet otherAsHashset: if (EqualityComparer>.Default.Equals(origin.EqualityComparer, otherAsHashset.Comparer)) { + if (otherAsHashset.Count != origin.Count) + { + return false; + } return SetEqualsWithHashset(otherAsHashset, origin); } - break; - case ICollection otherAsICollectionGeneric: - // We check for < instead of != because other is not guaranteed to be a set, it could be a collection with duplicates. - if (otherAsICollectionGeneric.Count < origin.Count) + if (otherAsHashset.Count < origin.Count) { return false; } break; - case ICollection otherAsICollection: - if (otherAsICollection.Count < origin.Count) + case ICollection otherAsICollectionGeneric: + // We check for < instead of != because other is not guaranteed to be a set, it could be a collection with duplicates. + if (otherAsICollectionGeneric.Count < origin.Count) { return false; } diff --git a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs index d6a01aee099a26..12203d957186b7 100644 --- a/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs +++ b/src/libraries/System.Collections.Immutable/tests/ImmutableHashSetTest.cs @@ -31,6 +31,96 @@ public void CustomSort() new[] { "apple" }); } + [Fact] + public void SetEqualsMismatchedComparersOriginInsensitiveOtherSensitive() + { + var ignoreCaseSet = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a"); + var sensitiveSet = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "A"); + + Assert.True(ignoreCaseSet.SetEquals(sensitiveSet)); + } + + [Fact] + public void SetEqualsMismatchedComparersOriginSensitiveOtherInsensitive() + { + var sensitiveSetMain = ImmutableHashSet.Create(StringComparer.Ordinal, "a"); + var insensitiveMutable = new HashSet(StringComparer.OrdinalIgnoreCase) { "a", "A" }; + + Assert.True(sensitiveSetMain.SetEquals(insensitiveMutable)); + } + + [Fact] + public void SetEqualsICollectionWithDuplicatesValidatesCorrectness() + { + var ignoreCaseSet = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a"); + var listWithDupes = new List { "a", "a", "a", "a" }; + + Assert.True(ignoreCaseSet.SetEquals(listWithDupes)); + } + + [Fact] + public void SetEqualsDifferentContent() + { + var ignoreCaseSet = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a"); + var setB = ImmutableHashSet.Create(StringComparer.Ordinal, "b"); + + Assert.False(ignoreCaseSet.SetEquals(setB)); + } + + [Fact] + public void SetEqualsMismatchedComparersOtherCountSmaller() + { + var originTwoElements = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a", "b"); + var otherOneElement = ImmutableHashSet.Create(StringComparer.Ordinal, "a"); + + Assert.False(originTwoElements.SetEquals(otherOneElement)); + } + + [Fact] + public void SetEqualsMatchedComparersDifferentCounts() + { + var matchedSet1 = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b"); + var matchedSet2 = ImmutableHashSet.Create(StringComparer.Ordinal, "a"); + + Assert.False(matchedSet1.SetEquals(matchedSet2)); + } + + [Fact] + public void SetEqualsMatchedComparersSameContent() + { + var matchedSet1 = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b"); + var matchedSet2 = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b"); + + Assert.True(matchedSet1.SetEquals(matchedSet2)); + } + + [Fact] + public void SetEqualsEmptySetsDifferentComparers() + { + var empty1 = ImmutableHashSet.Empty.WithComparer(StringComparer.Ordinal); + var empty2 = ImmutableHashSet.Empty.WithComparer(StringComparer.OrdinalIgnoreCase); + + Assert.True(empty1.SetEquals(empty2)); + } + + [Fact] + public void SetEqualsMismatchedComparersOriginSensitiveOtherInsensitiveSameCount() + { + var sensitiveSet = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "A"); + var insensitiveSet = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a", "b"); + + Assert.False(sensitiveSet.SetEquals(insensitiveSet)); + } + + [Fact] + public void SetEqualsMismatchedComparersOtherIsLarger() + { + var origin = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a"); + var other = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b"); + + Assert.False(origin.SetEquals(other)); + } + [Fact] public void ChangeUnorderedEqualityComparer() {