HashSet
grows by doubling. So when you have 23,997,907 items in the list and try to add the next one, it tries to double the size of its backing array. And that allocation causes it to exceed available memory. I assume you're running this on a 32-bit system, because on a 64-bit system a HashSet<object>
can hold upwards of 89 million items. The limit is about 61.7 million items in the 32-bit runtime.
What you need to do is pre-allocate the HashSet
to hold as many items as you need. Unfortunately, there's no direct way to do that. HashSet
doesn't have a constructor that will pre-allocate it with a given capacity.
You can, however, create a List
, use it to initialize the HashSet
, and then call Clear
on the HashSet
. That ends up giving you a HashSet
that has no items in it, but a capacity of the max you requested. I showed how to do that in a blog post: More on .NET Collection Sizes.
The limits on HashSet
size are due to the two gigabyte limit in .NET. No single object can be larger than two gigabytes. The number is actually slightly smaller, due to allocation overhead.