Skip to content

DeferredList Class

A list that defers add/remove operations until ProcessChanges() is called. Safe for queueing structural changes during iteration.

internal class DeferredList<T>

Type parameters

T

The type of items in the list.

Inheritance System.Object → DeferredList\<T>

Remarks

Removal uses a double-buffer HashSet pattern: - O(1) amortized queuing per removal - O(n) single-pass application via RemoveAll (vs O(n×m) previously) - New removals queued inside callbacks go to the next ProcessChanges call, preserving deferred semantics and preventing infinite recursion

Contains() is O(1) via a HashSet mirror of the committed list. Add() is idempotent: duplicate queuing is silently dropped to preserve the _items/_itemSet mirror invariant (List allows duplicates, HashSet does not). If the item is committed but pending removal, Add cancels the removal so the net effect of Remove → Add within one frame is "item stays". IsQueuedForRemoval() checks both the pending and active-processing buffers so callers inside a removal callback cannot accidentally re-queue the same item.

Properties
Count Gets the current count (excluding pending changes).
HasPendingChanges Gets whether there are pending changes.
Methods
Add(T) Queues an item to be added. If the item is committed and pending removal, the removal is cancelled so the net effect of Remove → Add is "item stays". No-op if the item is already committed (without pending removal) or already queued for add. O(1) via HashSet mirrors.
AsReadOnly() Gets a read-only view of the current committed items. The wrapper is created once and cached; it reflects all live changes to the list.
Clear() Clears all items and pending changes.
Contains(T) Checks if an item exists in the current committed list (not including pending adds). O(1).
GetEnumerator() Gets an enumerator for the current committed items (safe for read-only iteration).
IsQueuedForRemoval(T) Checks if an item is queued for removal or is actively being removed. O(1). Checks both the pending buffer and the active-processing buffer so callers inside a removal callback (e.g., Entity.OnDestroy) cannot accidentally re-queue the same item.
ProcessAdds(Action<T>) Processes pending additions with a callback for each item added.
ProcessChanges() Processes all queued changes: adds first, then removes.
ProcessRemovals(Action<T>) Processes pending removals with a callback for each item removed. New removals queued inside the callback are deferred to the next call.
Remove(T) Queues an item to be removed. O(1) amortized.
SortCommitted(Comparison<T>) Sorts the committed items in-place using a stable sort. Preserves relative order of items with equal keys. Does not affect pending adds or removals.