Skip to content

Add struct enumerator and IEnumerable<int> to IntSet - #51

Merged
marius-bughiu merged 1 commit into
mainfrom
feature/int-set-enumeration
May 1, 2026
Merged

Add struct enumerator and IEnumerable<int> to IntSet#51
marius-bughiu merged 1 commit into
mainfrom
feature/int-set-enumeration

Conversation

@marius-bughiu

Copy link
Copy Markdown
Owner

Summary

Mirrors the dictionary-side enumeration work (PRs #47 / #48) on the set side. IntSet<THasher> now ships a struct Enumerator, a public GetEnumerator(), and IEnumerable<int> conformance, so foreach (int item in set) works without a wrapper and IntSet is ready for LINQ.

The out-of-band zero entry is yielded first when present, matching how the dictionaries surface their out-of-band default-key entry. A _version counter is bumped on every entry-point structural mutation (Add, TryAdd, Remove, Clear); the struct enumerator captures it on construction and re-checks it from MoveNext / Reset, so concurrent modification fast-fails with InvalidOperationException exactly the way BCL HashSet<T> does. No-op mutations (re-adding an existing item, removing an absent item, Clear on an empty set) deliberately do not bump the version, so active enumerators stay valid across them — also a regression target.

This is the first slice of issue #23CeleritySet<T, THasher> follows in a separate PR (the open-generic T path needs IsDefaultValue care that's worth its own review). Together they unblock the future IEnumerable<T> constructor on the sets and the post-1.1.0 IReadOnlySet<T> interface.

Changes

  • src/Celerity/Collections/IntSet.cs — add IEnumerable<int> interface, _version field, version bumps on TryAdd / Remove / Clear, public GetEnumerator(), struct Enumerator with BeforeZero / InArray / Done state machine.
  • src/Celerity.Tests/Collections/IntSetEnumerationTests.cs — 25 new tests (see test plan).
  • CHANGELOG.md, ROADMAP.md, ISSUES.md — documented under issue Add SIMD optimizations #23.

Test plan

  • dotnet build — 0 errors, no new warnings beyond the existing pre-existing analyzer noise.
  • dotnet test — 431 / 431 pass (25 new tests in IntSetEnumerationTests, all 406 prior tests still green).
  • Empty / single / many-entry enumeration.
  • Zero-first-when-present ordering contract.
  • Removal, zero-removal, and Clear reflected in subsequent enumeration.
  • Multi-resize survival from a tiny initial capacity (200 entries from capacity: 4).
  • Mutation-during-enumeration throws on MoveNext and Reset (insert, zero-insert, remove, zero-remove, clear).
  • No-op mutations (duplicate TryAdd, absent Remove, empty Clear) leave active enumerators valid.
  • Reset reusability and post-exhaustion Current reset.
  • Generic IEnumerable<int> and non-generic IEnumerable parity.
  • Open-generic path covered via IntSet<Int32Murmur3Hasher>.
  • LINQ smoke test (Count / Sum / Contains) confirming the boxed enumerator path.

@marius-bughiu
marius-bughiu merged commit 726fbd6 into main May 1, 2026
1 check passed
@marius-bughiu
marius-bughiu deleted the feature/int-set-enumeration branch July 24, 2026 22:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant