Closed
Description
Description
HashSet.TrimExcess (introduced in #66426 for .NET 9) sets Count=Capacity even if it doesn't have as many items. The excess items are default initialized, including the internal state the HashSet uses (hashcode and freelist links). This corrupts the hashset data structure as iterating will yield the uninitialized items but direct lookup will not see them.
Reproduction Steps
var Set = new HashSet<int>(200);
for (int i = 50; i < 60; i++)
Set.Add(i);
Console.WriteLine($"Set.Count = {Set.Count}");
Console.WriteLine($"Set.TrimExcess(20)");
Set.TrimExcess(20);
Console.WriteLine($"Set.Count = {Set.Count}");
Console.WriteLine($"Set.ToArray().Length = {Set.ToArray().Length}");
Console.WriteLine($"foreach (var item in set)");
foreach (var item in Set)
Console.WriteLine($" Set.Contains({item}) = {Set.Contains(item)}");
Expected behavior
Count remains as before the trimming.
Actual behavior
Count is increased to full capacity
Regression?
no, new API
Known Workarounds
don't use the method with a capacity > count (making the new API rather useless)
Configuration
.NET 9.0.0-preview.2.24080.1
Other information
No response