T.ChangeSet is an immutable before-to-after transition nested in a generated model. Create it through diff/capture factories rather than a public constructor. It implements ISparseChangeSet<T>.
Here state means Optional<T.Fragment?>. Both model and sparse-state overloads are available where listed.
| Member | Contract |
|---|---|
static ChangeSet Empty |
No transition. |
bool IsEmpty, bool IsChanged |
Complementary aggregate flags. |
| Model-specific properties | Read-only scalar, nested, keyed, dictionary, or set transitions. |
static ChangeSet Between(T before, T after) |
Derives transitions from models. |
static ChangeSet Between(state before, state after) |
Also represents missing/null root and member endpoints. |
static ChangeSet FromPatch(T baseline, T.Patch patch) |
Attaches a known baseline to commands. |
static ChangeSet FromPatch(state baseline, T.Patch patch) |
Presence-aware equivalent. |
static ChangeSet FromPayload(T.ChangePayload payload) |
Converts a fully known transition envelope. |
An unchanged scalar's Before and After are missing because there is no transition. They are not a request to remove the model property.
| Member | Contract |
|---|---|
T.Patch ToPatch() |
Projects desired commands, discarding baseline checks. |
T.ChangePayload ToPayload() |
Exports the typed transport envelope, applying redaction rules. |
ChangeSet Invert() |
Reverses before and after. |
ChangeSet Compose(ChangeSet next) |
Combines sequential, continuous transitions. Inconsistent intermediate endpoints are rejected. |
static ChangeSet Compose(ChangeSet first, ChangeSet second) |
Static equivalent. |
state ApplyToBaseline(state baseline) |
Applies the transition to its expected baseline. |
IEnumerable<SparseChangeRecord> EnumerateChanges() |
Flattens transitions into deterministic rows. |
IReadOnlyList<SparsePath> EnumerateChangedPaths() |
Lists changed paths. |
SparseChangeRecord? Find(SparsePath path) |
Exact flattened-record lookup, or null. |
SparseChangeRecord? Find<TValue>(SparsePath<T,TValue> path) |
Typed-path equivalent. |
SparseChangeRecord is in SparseTypes.Generated; it exposes Path, PathText, Before, After, and Kind. Its constructor accepts path, presence-aware boxed endpoints, and SparseChangeKind. Kind is Changed, Added, Removed, or Order. Some model member names collide with convenience enumeration names; the ISparseChangeSet contract remains the generic inspection entry point.
ToPayload() preserves changes to [JsonIgnore] members in the neutral payload; the JSON codec rejects serializing such a payload before writing bytes. Changes to [SparseTransportIgnore] members are rejected during payload export. Do not serialize ChangeSet directly as a substitute for ToPayload().
| Member | Contract |
|---|---|
RebaseResult<ChangeSet> RebaseOnto(T current, options = null) |
Reconciles against current without modifying it. |
RebaseResult<ChangeSet> RebaseOnto(state current, options = null) |
Presence-aware equivalent. |
bool TryApplyTo(T current, out T? updated, options = null) |
Rebases and returns a new model only on success. |
bool TryApplyTo(T current, out T? updated, out IReadOnlyList<SparseConflict>? conflicts, options = null) |
Also reports structured conflicts. |
bool TryApplyInPlace(T current, out IReadOnlyList<SparseConflict>? conflicts, options = null) |
Rebases and writes supported members into current. |
void ApplyInPlace(T current, options = null) |
Throwing equivalent; conflicts or immutable changed members cause InvalidOperationException. |
static Resolution BeginResolution(RebaseResult<ChangeSet> rebase, T current) |
Starts explicit conflict decisions. |
static Resolution BeginResolution(RebaseResult<ChangeSet> rebase, state current) |
Presence-aware equivalent. |
Every options parameter above is ChangePayloadRebaseOptions?. TryApplyTo does not mutate its input. In-place methods retain the root instance; unsupported immutable writes report InPlaceWriteUnavailable. Whole-root presence transitions that cannot yield a non-null model require the optional Fragment APIs.
Resolution also has constructors matching BeginResolution and exposes Current as optional Fragment state; inherited decisions are documented in rebase API.
ISparseChangeSet exposes IsEmpty, IsChanged, and EnumerateChangeRecords(). Shape-specific Try methods take a CLR member name and an out result: TryGetValueChange<TValue>, TryGetNestedChange, TryGetKeyedChange<TKey,TElement,TElementChange>, and TryGetDictionaryChange<TKey,TValue,TEdited>. They return false for missing members or incompatible shapes/types.
See state queries for FieldState and cached query views, and generated transitions for typed member details.
Uses the reference models.
var before = new ReferenceSettings { Theme = "light" };
var after = new ReferenceSettings { Theme = "dark" };
var changes = ReferenceSettings.ChangeSet.Between(before, after);
var oldTheme = changes.Theme.Before.Value;
var newTheme = changes.Theme.After.Value;
var undo = changes.Invert();
var roundTrip = changes.Compose(undo);The endpoints are "light" and "dark". roundTrip.IsEmpty is true.