A minimalist collection for ValueTypes with no allocations for small sets (<50 elements), using stackalloc and ArrayPool.
- Zero allocations for sets smaller than 50 elements
- Supports uniqueness (
Distinct) - Fast
Contains,Add,Removeoperations - Manual resource lifecycle control via
Release()(required because it is aref structand cannot rely on GC finalization) - Switches seamlessly from stack to pooled array when capacity grows
// Allocate buffer on the stack for 20 elements
Span<int> buffer = stackalloc int[20];
// Create DistinctListSlim over this buffer
var slim = new DistinctListSlim<int>(buffer, distinct: true);
// Add elements
slim.AddRange(new int[] { 1, 2, 3, 4 });
// Check existence
Console.WriteLine(slim.Contains(3)); // True
Console.WriteLine(slim.Contains(99)); // False
// Remove element
slim.Remove(3);
Console.WriteLine(slim.Contains(3)); // False
// Iterate over elements
foreach (var x in slim.AsSpan())
Console.Write($"{x} ");
// IMPORTANT: release rented array if growth occurred
slim.Release();Because DistinctListSlim is implemented as a ref struct, it cannot rely on GC finalization.
When the internal buffer grows beyond the stack allocation, it rents an array from ArrayPool.
To avoid memory leaks, you must call Release() manually when the container is no longer needed.
var buffer = stackalloc int[20];
var slim = new DistinctListSlim<int>(buffer, distinct: true);
// use slim...
slim.Release();
// return rented array to ArrayPool if allocated- Temporary unique collections in high‑performance code
- Avoiding GC pressure in tight loops or latency‑sensitive systems
- Lightweight replacement for HashSet or List when working with small sets of value types
- Scenarios where stack allocation is preferable for speed and locality
This project is licensed under the MIT License