Skip to content

Update and clarify IChangeToken docs - #55773

Open
svick wants to merge 1 commit into
dotnet:mainfrom
svick:changetoken-updates
Open

Update and clarify IChangeToken docs#55773
svick wants to merge 1 commit into
dotnet:mainfrom
svick:changetoken-updates

Conversation

@svick

@svick svick commented Aug 28, 2026

Copy link
Copy Markdown
Member

Updated conceptual docs for IChangeToken with .Net 11 changes and clarified ActiveChangeCallbacks behavior (this was updated in XML docs also in .Net 11).


Internal previews

File Preview link
docs/core/extensions/primitives.md Learn preview

Build report

@svick
svick requested review from mrek-msft and rosebyte and a lite review from Copilot August 28, 2026 14:12
@svick
svick requested review from a team and gewarren as code owners August 28, 2026 14:12
@dotnetrepoman dotnetrepoman Bot added this to the August 2026 milestone Aug 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the conceptual documentation for Microsoft.Extensions.Primitives change tokens to reflect newer IChangeToken/ChangeToken.OnChange behavior and clarify callback semantics.

Changes:

  • Refreshes article metadata (ms.date) and adds ai-usage frontmatter.
  • Clarifies IChangeToken.ActiveChangeCallbacks behavior, including implications for detecting changes.
  • Expands ChangeToken.OnChange guidance to cover nullable producers and .NET 11 async consumer overload behavior (with a link to the related breaking-change article).

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

:::code source="./snippets/primitives/change/Example.Static.cs" id="Static":::

Much like previous examples, you'll need an implementation of `IChangeToken` that is produced by the `changeTokenProducer`. The producer is defined as a `Func<IChangeToken>` and it's expected that this will return a new token every invocation. The `consumer` is an `Action` or `Func<Task>` when not using `state`, or an `Action<TState>` or `Func<TState, Task>` where the generic type `TState` flows through the change notification.
Much like previous examples, you'll need an implementation of `IChangeToken` that the `changeTokenProducer` produces. The producer is a `Func<IChangeToken?>`. After a change, it should return a new token for the next registration. If it returns `null`, `ChangeToken.OnChange` doesn't register a callback. Dispose the `IDisposable` returned by `OnChange` to unregister the consumer.

For a synchronous consumer, pass an `Action` or `Action<TState>`. Exceptions from the producer or consumer propagate to the caller that registers or triggers the token.

Starting in .NET 11, you can pass a `Func<Task>` or `Func<TState, Task>` for an asynchronous consumer. `ChangeToken.OnChange` waits for the returned task to complete before the consumer can be invoked again. This behavior prevents concurrent consumer calls, but it can combine multiple changes that occur while the task runs into one later callback. An exception thrown before the consumer returns its task propagates to the code that registers or triggers the token. Exceptions that occur after the task is returned are left unobserved by `ChangeToken.OnChange`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants