Collections
The Ceres.Collections namespace provides small runtime collections used by Ceres systems. SparseArray<T> is the main public container; the remaining types are focused helpers rather than a general-purpose collections library.
SparseArray
SparseArray<T> assigns an integer slot when an element is added. Removing an element leaves a hole and does not move other allocated elements. A later Add reuses a free slot before growing the backing storage.
Use it when another structure needs to retain array-like indices while unrelated elements are inserted or removed, such as runtime registries and handle tables. Use List<T> when elements should remain contiguous or their indices do not escape the collection.
using Ceres.Collections;
var actors = new SparseArray<ActorState>(
length: 64,
capacity: 4096);
int playerIndex = actors.Add(new ActorState("Player"));
int enemyIndex = actors.Add(new ActorState("Enemy"));
actors.RemoveAt(playerIndex);
// enemyIndex still refers to the same allocated slot.
ActorState enemy = actors[enemyIndex];
// The next insertion may reuse playerIndex.
int replacementIndex = actors.Add(new ActorState("Replacement"));
The constructor arguments have distinct roles:
lengthcreates that many initially free slots.capacityis the maximum number of backing slots.Addthrows when growth would exceed it.
Pass a non-negative length that does not exceed capacity; the constructor does not validate that relationship.
Slot contract
- An allocated index remains stable until that slot is removed.
- A removed index can be reused by a later
Add; the index alone is not a generation-safe handle. IsAllocated(index)distinguishes live slots from holes and returnsfalsefor an out-of-range index.- Reading an unallocated slot returns
default; writing one has no effect. RemoveAtexpects a currently allocated, in-range index.Countreports allocated elements, not backing-slot count.- Enumeration visits allocated elements in ascending slot order and skips holes.
AddUninitialized reserves a slot containing default. Clear returns every existing slot to the free list. Shrink removes only trailing free storage; it does not compact live elements or change their indices.
Use normal enumeration when the slot number is not required. Keep the indices returned by Add in the owning registry when later lookup by slot is required.
foreach (ActorState actor in actors)
{
Process(actor);
}
Capability index
| Type | Contract |
|---|---|
PriorityQueue<T> |
Binary min-heap for IComparable<T>. Peek and Dequeue return the smallest item. Enumeration exposes heap storage order, not sorted order. Empty access is the caller's responsibility. |
NativeCollectionsExtensions |
DisposeSafe guards disposal of NativeArray<T>, NativeList<T>, and NativeParallelMultiHashMap<TKey, TValue>. Resize grows a NativeArray<T> when needed and preserves an existing larger allocation; it does not preserve data when reallocating. |
IOCContainer |
Internal exact-type instance registry used by higher-level Ceres systems. It is not a public dependency-injection container. |
ArrayUtils |
Copy-based mutation and lookup helpers for managed arrays. Prefer List<T> for mutation-heavy code. |
RandomList<T> |
Weighted selection that avoids the immediately previous item and decays the selected weight. |
ShufflingExtension |
In-place Fisher-Yates shuffle plus small random-selection helpers for managed lists. |
PriorityQueue<T> uses the type's CompareTo result directly. Lower values are dequeued first:
using Ceres.Collections;
var queue = new PriorityQueue<int>();
queue.Enqueue(30);
queue.Enqueue(10);
queue.Enqueue(20);
int first = queue.Dequeue(); // 10