Skip to content

fix: ObserveCountChanged drops a count change that happens while subscribing - #140

Open
armadavalor wants to merge 1 commit into
Cysharp:masterfrom
armadavalor:fix/132-count-changed-subscribe-race
Open

armadavalor wants to merge 1 commit into
Cysharp:masterfrom
armadavalor:fix/132-count-changed-subscribe-race

Conversation

@armadavalor

Copy link
Copy Markdown

Fixes the lost count change in ObserveCountChanged described in #132.

Cause: the base observer constructor attached the CollectionChanged handler before the derived constructor initialized countPrev. A Reset raised in that window was compared against the default 0 and dropped, and the derived constructor then overwrote countPrev with the new count, so nothing could detect it afterwards.

Fix:

  • ObservableCollectionObserverBase gets a protected virtual OnBeforeAttach() hook that runs before the handler is attached. countPrev is initialized there.
  • The subscription is created under lock (collection.SyncRoot), so a change from another thread cannot land between attaching the handler and the notifyCurrentCount: true notification. This also covers the duplicated or out-of-order first value mentioned in the issue.

Verification: added ObserveCountChanged_ChangeWhileSubscribing, which uses the decorator from the issue to clear the collection right after the handler is attached. It fails without the change (nothing emitted) and passes with it. I only had a .NET 10 SDK with the runtime rolled forward (DOTNET_ROLL_FORWARD=Major), so the net8.0 test project ran on that:

Passed! - Failed: 0, Passed: 11, Skipped: 0, Total: 11 - ObservableCollections.R3.Tests.dll (net8.0)

Closes #132

@armadavalor
armadavalor force-pushed the fix/132-count-changed-subscribe-race branch from 9895b59 to beb6461 Compare November 2, 2026 19:55
@armadavalor
armadavalor force-pushed the fix/132-count-changed-subscribe-race branch from beb6461 to db0ecbc Compare November 2, 2026 19:56
@aetos382
aetos382 requested a balanced review from Copilot November 5, 2026 09:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

With notifyCurrentCount enabled, a reentrant attachment-time reset produces duplicate initial count notifications ([0, 0]) that the outer lock does not prevent.

1 open issue
What changed in this PR

This PR addresses lost count-change notifications during R3 ObserveCountChanged subscriptions, as reported in #132.

Changes:

  • Initializes the previous count through a new pre-attachment hook.
  • Locks subscription setup to prevent concurrent mutations between handler attachment and the initial notification.
  • Adds a regression test that clears the collection during handler attachment.
File Description
tests/​ObservableCollections.R3.Tests/​ObservableCollectionExtensionsTest.cs Adds an attach-time mutation helper and regression test.
src/​ObservableCollections.R3/​ObservableCollectionR3Extensions.cs Initializes count tracking before attachment and locks subscription setup.

Review effort: Balanced

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.

ObserveCountChanged: a count change during Subscribe is silently dropped — the handler is attached before countPrev is initialized

3 participants