Skip to content

Collection Extensions

Ilia Petrov-Komotskii edited this page Oct 7, 2026 · 3 revisions

Side-effect iteration, shuffle, sampling, and fill helpers. Namespace Mane.DotNet.

ForEach

using Mane.DotNet;

enemies.ForEach(e => e.Reset());

ids.ForEachCancellable(id =>
{
    Process(id);
    return id != stopAt; // false stops
});

Null list or null action throws. ForEachCancellable stops when breakFunc returns false.

Sampling

GetRandomList(collection, count, random, getMaxWithDuplicates = false) copies the source, then Fisher-Yates. Default: no duplicates. If the pool is smaller than count and getMaxWithDuplicates is true, the whole source is repeated until the length is reached, then the remainder is sampled without duplicates. O(n) memory.

List<Item> loot = table.GetRandomList(3, rng);
Item one = bag.RandomOrDefault(rng); // empty → default
Item alive = bag.RandomOrDefault(item => item.IsAlive, rng); // no match → default

RandomOrDefault(random) uses a list indexer when it can; otherwise reservoir sampling (single pass).

RandomOrDefault(predicate, random) picks a uniform match, or default when nothing matches. The predicate runs once per element. Arrays and List<T> are scanned directly; other lists use the indexer. Other sequences use one-pass reservoir sampling of the matches.

List<T>.RandomOrDefaultWithIdx(out int selectedIdx, random) also returns the index (-1 when empty).

Shuffle(list, random) is in-place Fisher-Yates.

Init / fill

list.InitWith(0, 16);                 // clear, 16 zeros
list.InitWith(() => new Slot());      // fill to current Capacity
array.FillWith(1);
grid.FillWith((x, y) => x + y);
array.Clear();                        // Array.Clear 1D/2D

InitWith returns the list (fluent). Capacity overloads use current Capacity, not Count.

Other

  • SelfConcat(list, times) — repeat the sequence times times.
  • AnyAtLeast(source, predicate, count) — at least count matches (count >= 1).
  • IsNullOrEmpty(collection) — null, empty, or zero-length string.
  • dictionary.Convert((k, v) => (k.ToString(), v * 2)) — new dictionary; duplicate output keys throw.

None of these methods are thread-safe.

Clone this wiki locally