- It is fully based on unmanaged memory, allowing developers to manipulate memory with lower overhead and more control, while offering a wide range of container types.
- The library provides extensive support for
Span<T>
andunsafe
operations, making it suitable for scenarios with strict performance and memory behavior requirements.
- ✅ GC-Free Allocation: Most container data is allocated using unmanaged memory, without relying on the CLR garbage collector.
- ✅ High Performance: Compact structures, memory alignment, zero boxing, and support for high-performance algorithms.
- ✅ Span Support: Most containers support
Span<T>
/ReadOnlySpan<T>
, enabling in-place modification and zero-copy data passing. - ✅ Thread-Safe Containers: Includes several concurrent container variants suitable for multithreaded environments.
- ✅ Easy Integration: Uses standard C#, making it easy to replace existing containers.
Most containers in the standard library cannot be used in unmanaged environments, and many lack support for Span<T>
or ReadOnlySpan<T>
.
For example:
List<T>
does not allow fast access viaSpan<T>
orReadOnlySpan<T>
, which limits both performance and development efficiency.- In older versions of .NET,
Dictionary<TKey, TValue>
does not expose direct references to values, requiring operations to be performed on copies instead. This adds unnecessary overhead in performance-critical scenarios. - In many cases, types like
string
are overkill when only aReadOnlySpan<char>
is needed. By usingNativeString
, it’s possible to avoid frequent string allocations and reduce GC pressure significantly.
- All containers are value types or wrap unmanaged pointers. Please avoid using them before proper initialization to prevent undefined behavior.
- Most containers require calling
Dispose()
after use to free unmanaged resources properly. - Usage of most containers is very similar to the standard library counterparts, with added convenience methods like converting to
Span<T>
orReadOnlySpan<T>
. - For short-lived containers, you can take advantage of the
using
statement to automatically callDispose()
. - For
StackallocCollection
series, you can use thestackalloc
syntax. Alternatively, you can provide any fixed buffer from outside, such as unmanaged memory or fixed managed memory. - For
NativeCollection
series, they act as wrappers around theUnsafeCollection
series and additionally store a handle pointer for managing the underlying resource. - For
UnsafeCollection
series, they do not store a handle pointer themselves and are implemented directly as structs, providing a more lightweight but less managed usage. - You can use
NativeMemoryAllocator.Custom
to override:public static void* Alloc(uint byteCount)
public static void* AllocZeroed(uint byteCount)
public static void Free(void* ptr)
- You can use
NativeHashCode.Custom
to override:public static int GetHashCode(ReadOnlySpan<byte> buffer)
.
- You can use
NativeString.Custom
to override:public static int GetHashCode(ReadOnlySpan<char> buffer)
.
This project is actively under development. Welcome your suggestions and feedback.
This project is licensed under the MIT License.
BitArray
ConcurrentDictionary<TKey, TValue>
ConcurrentHashSet<T>
ConcurrentQueue<T>
ConcurrentStack<T>
Deque<T>
Dictionary<TKey, TValue>
HashSet<T>
List<T>
MemoryStream
OrderedDictionary<TKey, TValue>
OrderedHashSet<T>
PriorityQueue<TKey, TValue>
Queue<T>
SortedDictionary<TKey, TValue>
SortedList<TKey, TValue>
SortedSet<T>
SparseSet<T>
Stack<T>
String
StringBuilder<T>