Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions Containers.Test/ContiguousSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,4 +452,37 @@ public void WorksWithStrings()
Assert.Contains("alpha", set);
Assert.Contains("bravo", set);
}

[TestMethod]
public void Remove_WithCustomComparer_RemovesItemEqualOnlyUnderComparer()
{
// Arrange
ContiguousSet<string> set = new(StringComparer.OrdinalIgnoreCase) { "Apple", "Banana" };

// Act
bool removed = set.Remove("APPLE");

// Assert
Assert.IsTrue(removed);
Assert.HasCount(1, set);
Assert.IsFalse(set.Contains("apple"));
string[] expectedItems = ["Banana"];
Assert.AreSequenceEqual(expectedItems, set);
}

[TestMethod]
public void Remove_WithCustomComparer_ThenAdd_KeepsSingleElement()
{
// Arrange
ContiguousSet<string> set = new(StringComparer.OrdinalIgnoreCase) { "Apple" };

// Act
set.Remove("APPLE");
set.Add("apple");

// Assert
Assert.HasCount(1, set);
string[] expectedItems = ["apple"];
Assert.AreSequenceEqual(expectedItems, set);
}
}
33 changes: 33 additions & 0 deletions Containers.Test/InsertionOrderSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,37 @@ public void WorksWithStrings_MaintainsInsertionOrder()
Assert.AreEqual("alpha", set.ElementAt(1)); // Second unique
Assert.AreEqual("bravo", set.ElementAt(2)); // Third unique
}

[TestMethod]
public void Remove_WithCustomComparer_RemovesItemEqualOnlyUnderComparer()
{
// Arrange
InsertionOrderSet<string> set = new(StringComparer.OrdinalIgnoreCase) { "Apple", "Banana" };

// Act
bool removed = set.Remove("APPLE");

// Assert
Assert.IsTrue(removed);
Assert.HasCount(1, set);
Assert.IsFalse(set.Contains("apple"));
string[] expectedItems = ["Banana"];
Assert.AreSequenceEqual(expectedItems, set);
}

[TestMethod]
public void Remove_WithCustomComparer_ThenAdd_KeepsSingleElement()
{
// Arrange
InsertionOrderSet<string> set = new(StringComparer.OrdinalIgnoreCase) { "Apple" };

// Act
set.Remove("APPLE");
set.Add("apple");

// Assert
Assert.HasCount(1, set);
string[] expectedItems = ["apple"];
Assert.AreSequenceEqual(expectedItems, set);
}
}
15 changes: 13 additions & 2 deletions Containers/ContiguousSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,19 @@ public bool Remove(T item)
return false;
}

// Find and remove from the array
int index = Array.IndexOf(items, item, 0, Count);
// Find and remove from the array, matching with the set's comparer so an item that is
// equal only under a custom comparer is removed from storage as well as the hash set
IEqualityComparer<T> comparer = uniquenessSet.Comparer;
int index = -1;
for (int i = 0; i < Count; i++)
{
if (comparer.Equals(items[i], item))
{
index = i;
break;
}
}

if (index >= 0)
{
Count--;
Expand Down
10 changes: 9 additions & 1 deletion Containers/InsertionOrderSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,15 @@ public bool Remove(T item)
return false;
}

items.Remove(item);
// Match with the set's comparer so an item that is equal only under a custom comparer
// is removed from the list as well as the hash set
IEqualityComparer<T> comparer = uniquenessSet.Comparer;
int index = items.FindIndex(x => comparer.Equals(x, item));
if (index >= 0)
{
items.RemoveAt(index);
}

return true;
}

Expand Down
Loading