From 580389770af226e9b3fb937a99cf0cca6e30719d Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Mon, 13 Apr 2026 18:42:58 -0700 Subject: [PATCH 01/23] docs: overhaul XML comments for ObservableCacheEx extension methods Add uniform event behavior tables (Add/Update/Remove/Refresh/OnError/OnCompleted), seealso cross-references, inheritdoc for secondary overloads, and 'Worth noting' sections across all 3 ObservableCacheEx partial class files (~306 overloads). Key improvements: - 77 event behavior tables describing exact per-change-reason behavior - 129 seealso cross-references linking related operators - 107 inheritdoc tags for secondary overloads with delta remarks - 36 'Worth noting' sections calling out non-obvious behavior - All old-style generic param descriptions replaced with specific text - Summaries trimmed to 1-3 sentences, detail moved to remarks --- .../Cache/ObservableCacheEx.SortAndBind.cs | 185 +- .../ObservableCacheEx.VirtualiseAndPage.cs | 185 +- src/DynamicData/Cache/ObservableCacheEx.cs | 4889 +++++++++-------- 3 files changed, 2799 insertions(+), 2460 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index 06c14e0d4..7cb3afb04 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -18,9 +18,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -38,10 +39,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// Bind and sort default options. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -60,9 +62,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The list to bind to. /// An observable which will emit change sets. + /// This is the primary Bind overload for paged data. It applies paged changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -75,10 +78,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The list to bind to. /// Bind and sort default options. /// An observable which will emit change sets. + /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -92,9 +96,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -112,10 +117,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// Bind and sort default options. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -134,9 +140,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The list to bind to. /// An observable which will emit change sets. + /// This is the primary Bind overload for virtualized data. It applies virtualized changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -149,10 +156,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The list to bind to. /// Bind and sort default options. /// An observable which will emit change sets. + /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -161,14 +169,8 @@ public static partial class ObservableCacheEx where TKey : notnull => new BindVirtualized(source, targetList, options).Run(); - /// - /// Bind sorted data to the specified collection, for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The list to bind to. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList) @@ -176,15 +178,8 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified collection, for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The list to bind to. - /// Bind and sort default options. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -193,15 +188,7 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, Comparer.Default, options); - /// - /// Bind sorted data to the specified collection. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The list to bind to. - /// The comparer to order the resulting dataset. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -211,15 +198,34 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparer, DynamicDataOptions.SortAndBind); /// - /// Bind sorted data to the specified collection. + /// Sorts the source changeset using and applies incremental changes + /// directly to , keeping it sorted in-place. + /// Combines the behavior of Sort and Bind into a single optimized step. /// /// The type of the object. /// The type of the key. - /// The source. - /// The list to bind to. + /// The source changeset stream. + /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. /// The comparer to order the resulting dataset. - /// Bind and sort default options. + /// Bind and sort options controlling reset threshold and initial capacity. /// An observable which will emit change sets. + /// + /// + /// This operator is the preferred replacement for the .Sort().Bind() chain. + /// It applies sort logic and collection mutations in a single pass, avoiding intermediate allocations. + /// + /// + /// EventBehavior + /// AddItem inserted at the correct sorted position in . + /// UpdateOld item removed and new item inserted at its sorted position. + /// RemoveItem removed from . + /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Large batches may trigger a full list reset (clear + re-add) instead of incremental moves, controlled by . This fires CollectionChanged with Reset action, which can be more efficient for UI virtualization but causes a visual flicker. + /// + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -229,15 +235,7 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparer, options, targetList).Run(); - /// - /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The list to bind to. - /// An observable of comparers which enables the sort order to be changed.> - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -247,15 +245,33 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparerChanged, DynamicDataOptions.SortAndBind); /// - /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. + /// Sorts the source changeset and applies incremental changes directly to , + /// re-sorting when the comparer observable emits a new comparer. /// /// The type of the object. /// The type of the key. - /// The source. - /// The list to bind to. - /// An observable of comparers which enables the sort order to be changed.> - /// Bind and sort default options. + /// The source changeset stream. + /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. + /// An observable of comparers which enables the sort order to be changed. + /// Bind and sort options controlling reset threshold and initial capacity. /// An observable which will emit change sets. + /// + /// + /// When emits a new comparer, all items are re-sorted and the target list is updated. + /// No data is emitted until the first comparer arrives. + /// + /// + /// EventBehavior + /// AddItem inserted at the correct sorted position in . + /// UpdateOld item removed and new item inserted at its sorted position. + /// RemoveItem removed from . + /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. + /// Comparer changedFull re-sort of all items. The target list is updated to reflect the new order. + /// OnErrorForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until the comparer observable produces its first value. Large batches or comparer changes may trigger a full list reset depending on . + /// + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -265,14 +281,8 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparerChanged, options, targetList).Run(); - /// - /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The resulting read only observable collection. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -280,15 +290,8 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The resulting read only observable collection. - /// Bind and sort default options. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -297,15 +300,7 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, options); - /// - /// Bind sorted data to the specified readonly observable collection. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The resulting read only observable collection. - /// The comparer to order the resulting dataset. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -314,16 +309,11 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparer, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection. - /// - /// The type of the object. - /// The type of the key. - /// The source. + /// + /// The source changeset stream. /// The resulting read only observable collection. /// The comparer to order the resulting dataset. - /// Bind and sort default options. - /// An observable which will emit change sets. + /// Bind and sort options controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -342,15 +332,7 @@ public static partial class ObservableCacheEx return new SortAndBind(source, comparer, options, observableCollection).Run(); } - /// - /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The resulting read only observable collection. - /// An observable of comparers which enables the sort order to be changed. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -359,16 +341,11 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparerChanged, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source. + /// + /// The source changeset stream. /// The resulting read only observable collection. - /// An observable of comparers which enables the sort order to be changed.> - /// Bind and sort default options. - /// An observable which will emit change sets. + /// An observable of comparers which enables the sort order to be changed. + /// Bind and sort options controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index d4a5f060c..325fe8e4e 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -12,16 +12,8 @@ namespace DynamicData; /// public static partial class ObservableCacheEx { - /// - /// Sort and virtualize the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The comparer to order the resulting dataset. - /// The virtualizing requests. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndVirtualize(this IObservable> source, IComparer comparer, IObservable virtualRequests) @@ -29,16 +21,8 @@ public static IObservable>> So where TKey : notnull => source.SortAndVirtualize(comparer, virtualRequests, new SortAndVirtualizeOptions()); - /// - /// Sort and virtualize the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable of comparers which enables the sort order to be changed.> - /// The virtualizing requests. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -53,16 +37,35 @@ public static IObservable>> So } /// - /// Sort and virtualize the underlying data from the specified source. + /// Sorts unsorted data using , then returns only items within the + /// virtual window defined by . /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer to order the resulting dataset. - /// The virtualizing requests. - /// Addition optimization options for virtualization. + /// The virtualizing requests (start index and page size). + /// Additional optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. + /// + /// + /// Combines sorting and index-based windowing. Only items within the current virtual window are emitted. + /// Use the observable comparer overload if you need to change sort order at runtime. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. + /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. + /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. + /// RefreshSort position is re-evaluated. Window membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until produces its first value. Changing the window can cause a full recalculation of visible items. + /// + /// + /// public static IObservable>> SortAndVirtualize( this IObservable> source, IComparer comparer, @@ -78,16 +81,35 @@ public static IObservable>> So } /// - /// Sort and virtualize the underlying data from the specified source. + /// Sorts unsorted data, then returns only the items within the virtual window defined by + /// (start index + size). Re-sorts when the comparer observable emits. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable of comparers which enables the sort order to be changed.> - /// The virtualizing requests. - /// Addition optimization options for virtualization. + /// The source changeset stream. + /// An observable of comparers which enables the sort order to be changed. + /// The virtualizing requests (start index and page size). + /// Additional optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. + /// + /// + /// Combines sorting and index-based windowing in a single operator. Only items within the + /// current virtual window are emitted downstream. The window is defined by a start index and size. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. + /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. + /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. + /// RefreshSort position is re-evaluated. Window membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until both the comparer observable and virtualRequests have produced their first values. Changing the window or comparer can cause a full recalculation of visible items. + /// + /// + /// public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -107,7 +129,7 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The virtualising requests. /// An observable which will emit virtual change sets. /// source. @@ -123,16 +145,25 @@ public static IObservable> Virtualise - /// Limits the size of the result set to the specified number, ordering by the comparer. + /// Returns the top items from the source, sorted by . + /// Equivalent to SortAndVirtualize with a fixed window starting at index 0. /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer. - /// The size. + /// The maximum number of items to return. /// An observable which will emit virtual change sets. /// source. /// size;Size should be greater than zero. + /// + /// + /// Internally delegates to + /// with a fixed of (0, size). + /// + /// Worth noting: When the Nth item is displaced by a new item with higher sort priority, the displaced item is emitted as a Remove and the new item as an Add. + /// + /// public static IObservable>> Top(this IObservable> source, IComparer comparer, int size) where TObject : notnull where TKey : notnull @@ -153,7 +184,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The size. /// An observable which will emit virtual change sets. /// source. @@ -173,16 +204,8 @@ public static IObservable> Top(t return new Virtualise(source, Observable.Return(new VirtualRequest(0, size))).Run(); } - /// - /// Sort and page the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The comparer to order the resulting dataset. - /// The virtualizing requests. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndPage(this IObservable> source, IComparer comparer, IObservable pageRequests) @@ -190,16 +213,8 @@ public static IObservable>> SortA where TKey : notnull => source.SortAndPage(comparer, pageRequests, new SortAndPageOptions()); - /// - /// Sort and page the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable of comparers which enables the sort order to be changed.> - /// The virtualizing requests. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -214,16 +229,34 @@ public static IObservable>> SortA } /// - /// Sort and page the underlying data from the specified source. + /// Sorts unsorted data using , then pages the result using + /// . /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer to order the resulting dataset. - /// The virtualizing requests. - /// Addition optimization options for virtualization. - /// An observable which will emit virtual change sets. + /// The page requests (page number and page size). + /// Additional optimization options for paging. + /// An observable which will emit paged change sets. /// source. + /// + /// + /// Combines sorting and page-based windowing. Only items on the current page are emitted. + /// Use the observable comparer overload if you need to change sort order at runtime. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. + /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. + /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. + /// RefreshSort position is re-evaluated. Page membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until produces its first value. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. + /// + /// public static IObservable>> SortAndPage( this IObservable> source, IComparer comparer, @@ -239,16 +272,34 @@ public static IObservable>> SortA } /// - /// Sort and page the underlying data from the specified source. + /// Sorts unsorted data, then pages the result using page number and page size from + /// . Re-sorts when the comparer observable emits. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable of comparers which enables the sort order to be changed.> - /// The virtualizing requests. - /// Addition optimization options for virtualization. - /// An observable which will emit virtual change sets. + /// The source changeset stream. + /// An observable of comparers which enables the sort order to be changed. + /// The page requests (page number and page size). + /// Additional optimization options for paging. + /// An observable which will emit paged change sets. /// source. + /// + /// + /// Combines sorting and page-based windowing in a single operator. Only items on the current page + /// are emitted downstream. The page is defined by a 1-based page number and page size. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. + /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. + /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. + /// RefreshSort position is re-evaluated. Page membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until both the comparer observable and pageRequests have produced their first values. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. + /// + /// public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -268,7 +319,7 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The page requests. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 4edf35285..ad6a7ac30 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -28,18 +28,32 @@ public static partial class ObservableCacheEx private const bool DefaultResortOnSourceRefresh = true; /// - /// Inject side effects into the stream using the specified adaptor. + /// Injects a side effect into the changeset stream by calling . + /// for every changeset, then forwarding it downstream unchanged. /// - /// The type of the object. + /// The type of items in the cache. /// The type of the key. - /// The source. - /// The adaptor. - /// An observable which will emit change sets. - /// - /// source - /// or - /// destination. - /// + /// The source changeset stream. + /// The adaptor whose Adapt method is called for each changeset. + /// An observable that emits the same changesets as , after the adaptor has processed each one. + /// + /// + /// This is a thin wrapper around Rx's Do operator. The adaptor receives each changeset + /// as a side effect; the changeset itself is forwarded downstream unmodified. + /// + /// + /// EventBehavior + /// AddPassed to the adaptor, then forwarded. + /// UpdatePassed to the adaptor, then forwarded. + /// RemovePassed to the adaptor, then forwarded. + /// RefreshPassed to the adaptor, then forwarded. + /// OnErrorForwarded to the downstream observer. The adaptor is not called. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. + /// + /// public static IObservable> Adapt(this IObservable> source, IChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -50,19 +64,10 @@ public static IObservable> Adapt(this I return source.Do(adaptor.Adapt); } - /// - /// Inject side effects into the stream using the specified sorted adaptor. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The adaptor. - /// An observable which will emit change sets. - /// - /// source - /// or - /// destination. - /// + /// + /// The source sorted changeset stream. + /// The sorted adaptor whose Adapt method is called for each sorted changeset. + /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -74,13 +79,28 @@ public static IObservable> Adapt(this I } /// - /// Adds or updates the cache with the specified item. + /// Adds or updates the cache with the specified item, producing a changeset with a single Add + /// (if the key is new) or Update (if the key already exists). /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to add or update. + /// + /// Convenience method that wraps a single-item mutation inside . + /// + /// EventBehavior + /// AddProduced when the key does not already exist in the cache. + /// UpdateProduced when the key already exists. The previous value is included in the changeset. + /// RemoveNot produced by this method. + /// RefreshNot produced by this method. + /// OnErrorNot applicable (synchronous mutation). + /// OnCompletedNot applicable (synchronous mutation). + /// + /// + /// is null. + /// + /// public static void AddOrUpdate(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -90,15 +110,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item)); } - /// - /// Adds or updates the cache with the specified item. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The item. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache. + /// The item to add or update. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -108,16 +124,10 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item, equalityComparer)); } - /// - /// - /// Adds or updates the cache with the specified items. - /// - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The items. - /// source. + /// + /// The source cache. + /// The items to add or update. + /// Batch overload. All items are added/updated inside a single call, producing one changeset. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -127,17 +137,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items)); } - /// - /// - /// Adds or updates the cache with the specified items. - /// - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The items. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache. + /// The items to add or update. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -147,15 +151,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items, equalityComparer)); } - /// - /// Adds or updates the cache with the specified item / key pair. - /// - /// The type of the object. - /// The type of the key. - /// The source cache. + /// + /// The source intermediate cache. /// The item to add or update. - /// The key to add or update. - /// source. + /// The key to associate with the item. + /// This overload operates on , which requires an explicit key parameter. public static void AddOrUpdate(this IIntermediateCache source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -172,7 +172,7 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The others. /// An observable which emits change sets. /// source or others. @@ -192,7 +192,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. /// /// source @@ -214,7 +214,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -231,7 +231,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -248,7 +248,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -260,13 +260,14 @@ public static IObservable> And(this IOb } /// - /// Converts the source to an read only observable cache. + /// Wraps an in a read-only facade, hiding the mutable API. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable cache. - /// source. + /// The source cache to wrap. + /// A read-only . + /// is null. + /// public static IObservableCache AsObservableCache(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -277,14 +278,24 @@ public static IObservableCache AsObservableCache(t } /// - /// Converts the source to a readonly observable cache. + /// Materializes a changeset stream into a queryable, read-only . + /// The cache subscribes to the source on first access and maintains a live snapshot of all items. /// /// The type of the object. /// The type of the key. - /// The source. - /// if set to true all methods are synchronised. There is no need to apply locking when the consumer can be sure the read / write operations are already synchronised. - /// An observable cache. - /// source. + /// The source changeset stream. + /// If true (default), all cache operations are synchronized. Set to false when the caller guarantees single-threaded access. + /// A read-only observable cache that reflects the current state of the pipeline. + /// + /// + /// Disposing the returned cache unsubscribes from the source stream. The cache's Connect() + /// method provides a changeset stream of its own, which re-emits the current state on each new subscriber. + /// + /// When is false, a is used internally. + /// + /// is null. + /// + /// public static IObservableCache AsObservableCache(this IObservable> source, bool applyLocking = true) where TObject : notnull where TKey : notnull @@ -302,34 +313,48 @@ public static IObservableCache AsObservableCache(t #if SUPPORTS_ASYNC_DISPOSABLE /// /// - /// Automatically disposes items within the source collection, upon removal of the collection or teardown of the operator. - /// - /// - /// Individual items are disposed after removal or replacement changes have been sent downstream. - /// All items previously-published on the stream are disposed after the stream finalizes. - /// This includes both upstream completion or failure, or downstream un-subscription. + /// Disposes items implementing or when they are removed or replaced, + /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. /// /// - /// Disposal is supported for both and items. - /// Items implementing neither of these interfaces are unaffected by this operator. + /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators + /// see the removal before disposal occurs. Items implementing neither disposal interface are ignored. /// /// - /// The type of items in the source collection. - /// The type of key values used to uniquely identify items in the source collection. - /// A stream of changes from the source collection. + /// The type of items in the cache. + /// The type of the key. + /// The source changeset stream. /// /// - /// An action to be invoked upon each subscription to this operator, allowing the consumer access to the "disposalsCompleted" stream for that subscription. + /// Invoked once per subscription, providing an that signals when all + /// calls have finished. The signal emits a single value + /// and then completes. /// /// - /// The "disposalsCompleted" stream allows the consumer to properly observe the asynchronous disposal of any items that are disposed by the operator. This stream will emit a single value, and then complete, upon successfull completion of all invocations performed by the operator. + /// This is delivered on a separate channel from the main changeset stream so it can be observed even + /// if the source stream errors. /// + /// + /// A stream that forwards all changesets from unchanged. + /// /// - /// Providing these notifications within a downstream channel separate from the main collection change stream ensures that these notifications can be observed even in the event of a failure within the operator, or within stream. + /// Change reason handling: + /// + /// EventBehavior + /// AddTracks the item. No disposal. + /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. + /// RemoveDisposes the removed item. + /// RefreshPassed through. No disposal. + /// /// - /// - /// A stream containing copies of all changes observed from . - /// Throws for and . + /// + /// On stream completion, error, or subscription disposal, all items still in the cache are disposed. + /// items are disposed synchronously; items + /// are dispatched via the signal. + /// + /// + /// or is null. + /// public static IObservable> AsyncDisposeMany( this IObservable> source, Action> disposalsCompletedAccessor) @@ -428,6 +453,9 @@ public static IObservable> AutoRefreshOnObservableBatch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. /// The scheduler. /// An observable change set with additional refresh changes. + /// + /// Worth noting: Per-item observable errors are silently ignored (not forwarded to the downstream observer). Only source stream errors propagate. + /// public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -439,17 +467,34 @@ public static IObservable> AutoRefreshOnObservable - /// Batches the updates for the specified time period. + /// Collects changesets emitted within a time window and merges them into a single changeset. + /// Uses Rx's Buffer operator followed by . /// /// The type of the object. /// The type of the key. - /// The source. - /// The time span. - /// The scheduler. - /// An observable which emits change sets. - /// source - /// or - /// scheduler. + /// The source changeset stream. + /// The time window for batching. + /// The scheduler for timing. Defaults to . + /// An observable that emits merged changesets, one per time window. + /// + /// + /// All changesets received during the time window are concatenated into a single changeset. + /// This is useful for reducing UI update frequency when the source emits many rapid changes. + /// + /// + /// EventBehavior + /// AddBuffered and included in the merged changeset at the end of the time window. + /// UpdateBuffered and included in the merged changeset. + /// RemoveBuffered and included in the merged changeset. + /// RefreshBuffered and included in the merged changeset. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedAny remaining buffered changes are flushed, then completion is forwarded. + /// + /// Worth noting: The merged changeset may contain contradictory changes (e.g., Add then Remove for the same key). Downstream operators handle this correctly, but raw inspection of the changeset may be surprising. + /// + /// is null. + /// + /// public static IObservable> Batch(this IObservable> source, TimeSpan timeSpan, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -459,66 +504,55 @@ public static IObservable> Batch(this I return source.Buffer(timeSpan, scheduler ?? GlobalConfig.DefaultScheduler).FlattenBufferResult(); } - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload delegates to the primary overload with initialPauseState: false. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, scheduler); - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload delegates to the primary overload with default initialPauseState: false. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, scheduler: scheduler).Run(); - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload omits initialPauseState (defaults to false) but accepts a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, timeOut, scheduler); /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. + /// Conditionally buffers changesets while a pause signal is active, then flushes all buffered + /// changes as a single merged changeset when the signal resumes. /// /// The type of the object. /// The type of the key. - /// The source. - /// When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// The source changeset stream. + /// When true, buffering begins. When false, the buffer is flushed. + /// If true, starts in a paused (buffering) state. + /// Maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. + /// The scheduler for timeout timing. + /// An observable that emits changesets, buffered or passthrough depending on pause state. + /// + /// + /// While paused, incoming changesets are accumulated. On resume (or timeout), all buffered changesets + /// are merged into a single changeset and emitted. While not paused, changesets pass through immediately. + /// + /// + /// EventBehavior + /// AddBuffered while paused; forwarded immediately while active. + /// UpdateBuffered while paused; forwarded immediately while active. + /// RemoveBuffered while paused; forwarded immediately while active. + /// RefreshBuffered while paused; forwarded immediately while active. + /// OnErrorForwarded to the downstream observer. Buffered data is lost. + /// OnCompletedForwarded. Any remaining buffered data is flushed before completion. + /// + /// Worth noting: If the source completes while paused, buffered data IS flushed before OnCompleted. However, if the source errors while paused, buffered data is lost. + /// + /// or is null. + /// + /// public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -529,19 +563,13 @@ public static IObservable> BatchIf(this return new BatchIf(source, pauseIfTrueSelector, timeOut, initialPauseState, scheduler: scheduler).Run(); } - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// Specify a time observable. The buffer will be emptied each time the timer produces a value and when it completes. On completion buffering will cease. + /// + /// The source changeset stream. + /// When true, buffering begins. When false, the buffer is flushed. + /// If true, starts in a paused (buffering) state. + /// An observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. /// The scheduler. - /// An observable which emits change sets. - /// source. + /// This overload accepts an explicit timer observable instead of a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IObservable? timer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, timer, scheduler).Run(); @@ -551,7 +579,7 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. @@ -578,7 +606,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// The binding options. /// An observable which will emit change sets. @@ -597,7 +625,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// The updater. /// An observable which will emit change sets. @@ -628,7 +656,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// The binding options. /// An observable which will emit change sets. @@ -649,7 +677,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// The number of changes before a reset notification is triggered. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. @@ -685,7 +713,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// An observable which will emit change sets. /// source. @@ -704,7 +732,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// The binding options. /// An observable which will emit change sets. @@ -725,7 +753,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The destination. /// The updater. /// An observable which will emit change sets. @@ -756,7 +784,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// The binding options. /// An observable which will emit change sets. @@ -779,7 +807,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. @@ -813,7 +841,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source. + /// The source changeset stream. /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. @@ -837,7 +865,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source. + /// The source changeset stream. /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. @@ -859,14 +887,24 @@ public static IObservable> Bind(this IO #endif /// - /// Buffers changes for an initial period only. After the period has elapsed, not further buffering occurs. + /// Buffers the initial burst of changesets for the specified duration, merges them into a single + /// changeset, then passes all subsequent changesets through without buffering. /// /// The object type. /// The type of the key. /// The source change set. - /// The period to buffer, measure from the time that the first item arrives. - /// The scheduler to buffer on. - /// An observable which emits change sets. + /// The time window to buffer, measured from when the first changeset arrives. + /// The scheduler for timing. Defaults to . + /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. + /// + /// + /// Useful for aggregating the initial snapshot (which may arrive as many small changesets) into a + /// single changeset for efficient downstream processing, while leaving subsequent live updates untouched. + /// + /// Internally uses , Rx Buffer, and . + /// + /// + /// public static IObservable> BufferInitial(this IObservable> source, TimeSpan initialBuffer, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => source.DeferUntilLoaded().Publish( @@ -878,15 +916,28 @@ public static IObservable> BufferInitial - /// Cast the object to the specified type. - /// Alas, I had to add the converter due to type inference issues. + /// Casts each item in the changeset to a new type using the provided converter function. + /// Equivalent to + /// but named for discoverability when a simple type cast or conversion is needed. /// - /// The type of the object. + /// The type of the source object. /// The type of the key. - /// The type of the destination. - /// The source. - /// The conversion factory. - /// An observable which emits change sets. + /// The type of the destination object. + /// The source changeset stream. + /// The conversion function applied to each item. + /// An observable changeset of converted items. + /// + /// + /// EventBehavior + /// AddCalls and emits an Add with the converted item. + /// UpdateCalls on the new value and emits an Update. + /// RemoveEmits a Remove. The converter is not called. + /// RefreshForwarded as Refresh. The converter is not called. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// public static IObservable> Cast(this IObservable> source, Func converter) where TSource : notnull where TKey : notnull @@ -898,14 +949,27 @@ public static IObservable> Cast - /// Changes the primary key. + /// Re-keys each item in the changeset by applying to the current item. + /// The original change reason is preserved; only the key is remapped. /// /// The type of the object. /// The type of the source key. /// The type of the destination key. - /// The source. - /// The key selector eg. (item) => newKey. - /// An observable which emits change sets. + /// The source changeset stream. + /// A function that computes the destination key from the item, e.g. (item) => item.NewId. + /// An observable changeset with items re-keyed using . + /// + /// + /// EventBehavior + /// Add is called on the item. An Add is emitted with the destination key. + /// Update is called on the current item. An Update is emitted with the destination key. If the key selector produces a different destination key for the updated value than it did for the original value, downstream consumers will see an Update for a key that may not match the original Add. + /// Remove is called on the item. A Remove is emitted with the destination key. + /// Refresh is called on the item. A Refresh is emitted with the destination key. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -922,16 +986,11 @@ public static IObservable> ChangeKey - /// Changes the primary key. - /// - /// The type of the object. - /// The type of the source key. - /// The type of the destination key. - /// The source. - /// The key selector eg. (key, item) => newKey. - /// An observable which emits change sets. - /// source. + /// + /// + /// This overload also provides the source key to , + /// allowing the destination key to be derived from both the item and its original key. + /// public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -949,12 +1008,23 @@ public static IObservable> ChangeKey - /// Clears all data. + /// Removes all items from the cache, producing a changeset with a Remove for every item. /// /// The type of the object. /// The type of the key. - /// The source. - /// source. + /// The source cache to clear. + /// + /// + /// EventBehavior + /// AddNot produced by this operation. + /// UpdateNot produced by this operation. + /// RemoveA Remove is emitted for every item currently in the cache. + /// RefreshNot produced by this operation. + /// OnErrorNot applicable (synchronous mutation method). + /// OnCompletedNot applicable (synchronous mutation method). + /// + /// + /// is null. public static void Clear(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -964,13 +1034,7 @@ public static void Clear(this ISourceCache source) source.Edit(updater => updater.Clear()); } - /// - /// Clears all items from the cache. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// source. + /// public static void Clear(this IIntermediateCache source) where TObject : notnull where TKey : notnull @@ -980,13 +1044,7 @@ public static void Clear(this IIntermediateCache s source.Edit(updater => updater.Clear()); } - /// - /// Clears all data. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// source. + /// public static void Clear(this LockFreeObservableCache source) where TObject : notnull where TKey : notnull @@ -996,13 +1054,25 @@ public static void Clear(this LockFreeObservableCache - /// Clones the changes into the specified collection. + /// Applies each change from the source changeset to the specified collection as a side effect. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source. - /// The target. - /// An observable which emits change sets. + /// The source changeset stream. + /// The target collection to which changes are applied. + /// An observable that forwards all changesets from unchanged. + /// + /// + /// EventBehavior + /// AddThe item is added to . Forwarded as Add. + /// UpdateThe previous item is removed from and the current item is added. Forwarded as Update. + /// RemoveThe item is removed from . Forwarded as Remove. + /// RefreshIgnored ( has no concept of refresh). Forwarded as Refresh. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// public static IObservable> Clone(this IObservable> source, ICollection target) where TObject : notnull where TKey : notnull @@ -1041,13 +1111,12 @@ public static IObservable> Clone(this I } /// - /// Convert the object using the specified conversion function. - /// This is a lighter equivalent of Transform and is designed to be used with non-disposable objects. + /// Obsolete: use instead. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source. + /// The source changeset stream. /// The conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] @@ -1068,12 +1137,26 @@ public static IObservable> Convert - /// Defer the subscription until the stream has been inflated with data. + /// Suppresses all emissions until the first non-empty changeset arrives, then replays that changeset and all subsequent ones. + /// If the source never produces a non-empty changeset, the stream waits indefinitely. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change sets. + /// The source changeset stream. + /// An observable that begins emitting changesets once the first non-empty changeset is received. + /// + /// + /// EventBehavior + /// AddForwarded as Add once the initial non-empty changeset has been received. + /// UpdateForwarded as Update once loaded. + /// RemoveForwarded as Remove once loaded. + /// RefreshForwarded as Refresh once loaded. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Blocks indefinitely if the cache or stream never receives any data. Ensure the source will eventually emit at least one changeset. + /// + /// public static IObservable> DeferUntilLoaded(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1083,13 +1166,7 @@ public static IObservable> DeferUntilLoaded(source).Run(); } - /// - /// Defer the subscription until the stream has been inflated with data. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable which emits change sets. + /// public static IObservable> DeferUntilLoaded(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -1100,17 +1177,39 @@ public static IObservable> DeferUntilLoaded - /// Disposes each item when no longer required. /// - /// Individual items are disposed after removal or replacement changes have been sent downstream. - /// All items previously-published on the stream are disposed after the stream finalizes. + /// Disposes items implementing when they are removed or replaced, + /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. + /// + /// + /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators + /// see the removal before disposal occurs. Items that do not implement are ignored. /// /// /// The type of the object. /// The type of the key. - /// The source. - /// A continuation of the original stream. - /// source. + /// The source changeset stream. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddTracks the item. No disposal. + /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. + /// RemoveDisposes the removed item. + /// RefreshPassed through. No disposal. + /// + /// + /// + /// On stream completion, error, or subscription disposal, all remaining tracked items are disposed. + /// All disposal is synchronous via . + /// For items that implement , use instead. + /// + /// + /// is null. + /// + /// public static IObservable> DisposeMany(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1126,11 +1225,12 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source. + /// The source changeset stream. /// The value selector. /// An observable which will emit distinct change sets. /// /// Due to it's nature only adds or removes can be returned. + /// Worth noting: Reference counting assumes value equality is transitive. Mutable value objects with inconsistent Equals implementations can corrupt ref counts. /// /// source. public static IObservable> DistinctValues(this IObservable> source, Func valueSelector) @@ -1144,16 +1244,14 @@ public static IObservable> DistinctValues>(observer => new DistinctCalculator(source, valueSelector).Run().SubscribeSafe(observer)); } - /// - /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items - /// in the list and amends only the differences. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The items to add, update or delete. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache to diff against. + /// The complete snapshot of items to diff against the cache. + /// An used to determine whether a new item is the same as an existing cached item. + /// + /// This overload uses an instead of a delegate + /// to determine item equality. + /// public static void EditDiff(this ISourceCache source, IEnumerable allItems, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -1166,15 +1264,26 @@ public static void EditDiff(this ISourceCache sour } /// - /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items - /// in the list and amends only the differences. + /// Diffs a complete snapshot of items against the current cache contents, producing the minimal set of + /// Add, Update, and Remove changes needed to bring the cache in sync with the snapshot. /// /// The type of the object. /// The type of the key. - /// The source. - /// The items to compare and add, update or delete. - /// Expression to determine whether an item's value is equal to the old value (current, previous) => current.Version == previous.Version. - /// source. + /// The source cache to diff against. + /// The complete snapshot of desired items. + /// A function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// + /// + /// EventBehavior + /// AddItems in whose key is not in the cache produce an Add. + /// UpdateItems present in both and the cache that differ (per ) produce an Update. + /// RemoveItems in the cache whose key is not in produce a Remove. + /// RefreshNot produced by this operation. + /// OnErrorNot applicable (synchronous mutation method). + /// OnCompletedNot applicable (synchronous mutation method). + /// + /// + /// , , or is null. public static void EditDiff(this ISourceCache source, IEnumerable allItems, Func areItemsEqual) where TObject : notnull where TKey : notnull @@ -1188,15 +1297,29 @@ public static void EditDiff(this ISourceCache sour } /// - /// Converts an Observable of Enumerable to an Observable ChangeSet that updates when the enumerables changes. Counterpart operator to . + /// Converts an of into a changeset stream by diffing each + /// emission against the previous one. Each emission replaces the entire dataset. + /// Counterpart to . /// /// The type of the object. /// The type of the key. - /// The source. - /// Key Selection Function for the ChangeSet. - /// Optional instance to use for comparing values. - /// An observable cache. - /// source. + /// The source observable of item snapshots. + /// A function to extract the unique key from each item. + /// Optional for comparing items. Uses default equality if null. + /// An observable changeset representing the incremental differences between successive snapshots. + /// + /// + /// EventBehavior + /// AddItems in the new snapshot whose key was not in the previous snapshot produce an Add. + /// UpdateItems present in both snapshots that differ (per ) produce an Update. + /// RemoveItems in the previous snapshot whose key is absent from the new snapshot produce a Remove. + /// RefreshNot produced by this operator. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. + /// public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1208,15 +1331,27 @@ public static IObservable> EditDiff(thi } /// - /// Converts an Observable Optional to an Observable ChangeSet that adds/removes/updates as the optional changes. + /// Converts an of into a changeset stream that tracks + /// a single item: Some produces an Add or Update, and None produces a Remove. /// /// The type of the object. /// The type of the key. - /// The source. - /// Key Selection Function for the ChangeSet. - /// Optional instance to use for comparing values. - /// An observable changeset. - /// source. + /// The source observable of optional values. + /// A function to extract the unique key from each item. + /// Optional for comparing items. Uses default equality if null. + /// An observable changeset tracking the single optional item. + /// + /// + /// EventBehavior + /// AddEmitted when the source produces Some(value) and no item was previously tracked. + /// UpdateEmitted when the source produces Some(value) and an item was already tracked with a different value (per ). + /// RemoveEmitted when the source produces None and an item was previously tracked. + /// RefreshNot produced by this operator. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1228,12 +1363,24 @@ public static IObservable> EditDiff(thi } /// - /// Ensures there are no duplicated keys in the observable changeset. + /// Validates that each changeset contains no duplicate keys. + /// If duplicates are detected, an is emitted via OnError. /// - /// The source change set. /// The type of the object. /// The type of the key. - /// A changeset which guarantees a key is only present at most once in the changeset. + /// The source changeset stream to validate. + /// A changeset stream guaranteed to contain unique keys per changeset. + /// + /// + /// EventBehavior + /// AddForwarded as Add if the key is unique within the changeset. + /// UpdateForwarded as Update if the key is unique within the changeset. + /// RemoveForwarded as Remove if the key is unique within the changeset. + /// RefreshForwarded as Refresh if the key is unique within the changeset. + /// OnErrorForwarded. Also emitted with if duplicate keys are detected in a changeset. + /// OnCompletedForwarded to the downstream observer. + /// + /// public static IObservable> EnsureUniqueKeys(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1249,7 +1396,7 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The others. /// An observable which emits change sets. /// @@ -1299,7 +1446,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1316,7 +1463,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1333,7 +1480,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1345,19 +1492,28 @@ public static IObservable> Except(this } /// - /// Automatically removes items from the stream after the time specified by - /// the timeSelector elapses. Return null if the item should never be removed. + /// Schedules automatic removal of items after the timeout returned by . + /// If returns null, the item never expires. /// /// The type of the object. /// The type of the key. - /// The source. - /// The time selector. - /// An observable which emits change sets. - /// - /// source - /// or - /// timeSelector. - /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// An observable changeset that includes timer-driven Remove changes for expired items. + /// + /// When a timer fires, a Remove is emitted for the expired item. + /// + /// EventBehavior + /// AddSchedules a removal timer based on . Forwarded as Add. + /// UpdateResets the removal timer for the item. Forwarded as Update. + /// RemoveCancels the removal timer. Forwarded as Remove. + /// RefreshForwarded as Refresh. No timer change. + /// OnErrorForwarded. All pending timers are cancelled. + /// OnCompletedForwarded. All pending timers are cancelled. + /// + /// Worth noting: A null return from means "never expire". Update changes reset the expiration timer. + /// + /// or is null. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector) @@ -1367,21 +1523,10 @@ public static IObservable> ExpireAfter( source: source, timeSelector: timeSelector); - /// - /// Automatically removes items from the stream after the time specified by - /// the timeSelector elapses. Return null if the item should never be removed. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The time selector. - /// The scheduler. - /// An observable which emits change sets. - /// - /// source - /// or - /// timeSelector. - /// + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// The scheduler used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1393,21 +1538,15 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, scheduler: scheduler); - /// - /// Automatically removes items from the stream on the next poll after the time specified by - /// the time selector elapses. - /// - /// The type of the object. - /// The type of the key. - /// The cache. - /// The time selector. Return null if the item should never be removed. - /// The polling interval. if this value is specified, items are expired on an interval. - /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. - /// - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// This is less accurate but more efficient when many items share similar expiration times. + /// + /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next + /// poll after their timeout elapses, which trades accuracy for reduced timer overhead. + /// public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1419,22 +1558,11 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, pollingInterval: pollingInterval); - /// - /// Automatically removes items from the stream on the next poll after the time specified by - /// the time selector elapses. - /// - /// The type of the object. - /// The type of the key. - /// The cache. - /// The time selector. Return null if the item should never be removed. - /// The polling interval. if this value is specified, items are expired on an interval. - /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. - /// - /// The scheduler. - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// The scheduler used to schedule polling and expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1449,21 +1577,22 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// Automatically removes items from the cache after the time specified by - /// the time selector elapses. + /// Automatically removes items from the after the timeout returned + /// by . Returns an observable of the removed key-value pairs (not a changeset stream). /// /// The type of the object. /// The type of the key. - /// The cache. - /// The time selector. Return null if the item should never be removed. - /// A polling interval. Since multiple timer subscriptions can be expensive, - /// it may be worth setting the interval. - /// - /// The scheduler. - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// The source cache from which expired items are removed. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// The scheduler used to schedule expiration timers. Defaults to if null. + /// An observable that emits the key-value pairs of items removed from the cache by expiration. + /// + /// Unlike the stream-based overloads, this operates directly on the + /// and returns the removed items as collections, + /// not as a changeset stream. + /// + /// or is null. public static IObservable>> ExpireAfter( this ISourceCache source, Func timeSelector, @@ -1478,14 +1607,29 @@ public static IObservable>> ExpireAfter< scheduler: scheduler); /// - /// Filters the specified source. + /// Filters items from the source changeset stream using a static predicate. + /// Only items that satisfy are included downstream. /// /// The type of the object. /// The type of the key. - /// The source. - /// The filter. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// The source changeset stream. + /// The predicate used to determine whether each item is included. + /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets, which can be useful for monitoring loading status. + /// An observable changeset containing only items that satisfy . + /// + /// + /// EventBehavior + /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. + /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshThe predicate is re-evaluated. If the item now passes but previously did not, an Add is emitted. If it still passes, a Refresh is forwarded. If it no longer passes, a Remove is emitted. If it still fails, the change is dropped. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Refresh events trigger re-evaluation, which can promote or demote items. Pair with for property-change-driven filtering. + /// + /// + /// public static IObservable> Filter( this IObservable> source, Func filter, @@ -1497,15 +1641,11 @@ public static IObservable> Filter( filter: filter, suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// Creates a filtered stream which can be dynamically filtered. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// Observable to change the underlying predicate. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// + /// + /// This overload does not accept a reapplyFilter signal. It is equivalent to calling the + /// full dynamic overload with as the reapply observable. + /// public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1518,19 +1658,34 @@ public static IObservable> Filter( suppressEmptyChangeSets: suppressEmptyChangeSets); /// - /// Creates a filtered stream which can be dynamically filtered, based on state values passed through to a static filtering predicate. + /// Creates a dynamically filtered stream where the filter predicate depends on external state. + /// Each emission from triggers a full re-filtering of all items. /// /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source. + /// The source changeset stream. /// A stream of state values to be passed to . - /// A static predicate to be used to determine which items should be included or excluded by the filter. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. - /// Throws for , , and . + /// A predicate that receives the current state and an item, returning true to include or false to exclude. + /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets. + /// An observable changeset containing only items satisfying for the latest state. + /// , , or is null. /// - /// Usually, should emit an initial value, immediately upon subscription. This is because cannot be invoked until the first state value is received, and accordingly, the operator will treat all items as excluded until then. Each value emitted by will trigger a full re-filtering of the entire collection. + /// + /// should emit an initial value immediately upon subscription. + /// Until the first state value arrives, no items pass the filter (all items are excluded). + /// Each subsequent state emission triggers a full re-evaluation of every item in the collection. + /// + /// + /// EventBehavior + /// AddEvaluated against the current state. If it passes, an Add is emitted. Otherwise dropped. + /// UpdateRe-evaluated. Four outcomes as with the static overload. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshRe-evaluated against the current state. May produce Add, Refresh, Remove, or be dropped. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: should emit an initial value immediately. Each emission triggers a full re-evaluation of all items, which can be expensive for large collections. /// public static IObservable> Filter( this IObservable> source, @@ -1546,16 +1701,17 @@ public static IObservable> Filter(), suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// Creates a filtered stream which can be dynamically filtered. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// Observable to change the underlying predicate. - /// Observable to re-evaluate whether the filter still matches items. Use when filtering on mutable values. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// + /// The source changeset stream. + /// An observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. + /// An observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. + /// When true (default), empty changesets are suppressed for performance. + /// + /// In addition to the per-item behavior described in the static overload, + /// emissions from replace the predicate and trigger full re-filtering, + /// while emissions from re-evaluate all items against the current predicate. + /// Worth noting: No items are included until the predicate observable emits its first value. + /// public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1591,6 +1747,15 @@ public static IObservable> Filter( /// Your filtering predicate runs quickly, and does not heavily allocate memory /// /// Note that, because filtering is purely deterministic, Refresh operations are transparently ignored by this operator. + /// + /// EventBehavior + /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. + /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshDropped. Because items are assumed immutable, there is nothing to re-evaluate. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// /// public static IObservable> FilterImmutable( this IObservable> source, @@ -1610,16 +1775,29 @@ public static IObservable> FilterImmutable - /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. + /// Filters items using a per-item that controls inclusion. + /// Each item's observable is created by and toggles the item in or out of the downstream stream. /// /// The type of the object. /// The type of the key. - /// The source. - /// Factory function used to create the observable bool that controls whether that given item passes the filter or not. - /// Optional time to buffer changes from the observable bools. - /// Optional scheduler to use when buffering the changes. - /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. - /// One of the given parameters was null. + /// The source changeset stream. + /// A factory that creates an for each item and its key. When the observable emits true, the item is included; when false, it is excluded. + /// Optional time window to buffer inclusion changes from per-item observables before re-evaluating. + /// Optional scheduler used for buffering. + /// An observable changeset containing only items whose per-item observable most recently emitted true. + /// + /// + /// EventBehavior + /// AddSubscribes to the per-item observable. When it first emits true, an Add is emitted downstream. Subsequent false/true emissions toggle inclusion (emitting Remove/Add). + /// UpdateDisposes the old item's subscription and subscribes to the new item's observable. Inclusion state is re-evaluated. + /// RemoveDisposes the item's subscription. If the item was included downstream, a Remove is emitted. + /// RefreshForwarded as Refresh if the item is currently included downstream. + /// OnErrorForwarded. Also triggered if any per-item observable errors. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. + /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1630,17 +1808,10 @@ public static IObservable> FilterOnObservable(source, filterFactory, buffer, scheduler).Run(); } - /// - /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// Factory function used to create the observable bool that controls whether that given item passes the filter or not. - /// Optional time to buffer changes from the observable bools. - /// Optional scheduler to use when buffering the changes. - /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. - /// One of the given parameters was null. + /// + /// + /// This overload does not provide the key to ; only the item is passed. + /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1652,13 +1823,12 @@ public static IObservable> FilterOnObservable - /// Ensure that finally is always called. Thanks to Lee Campbell for this. + /// Obsolete: do not use. This can cause unhandled exception issues. Use the standard Rx Finally operator instead. /// /// The type contained within the observables. - /// The source. + /// The source changeset stream. /// The finally action. /// An observable which has always a finally action applied. - /// source. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) { @@ -1669,13 +1839,15 @@ public static IObservable FinallySafe(this IObservable source, Action f } /// - /// Flattens an update collection to it's individual items. + /// Unwraps each into individual + /// values via . /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change set values on a flatten result. - /// source. + /// The source changeset stream. + /// An observable of individual values. + /// is null. + /// public static IObservable> Flatten(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1686,12 +1858,14 @@ public static IObservable> Flatten(this IOb } /// - /// Convert the result of a buffer operation to a single change set. + /// Merges a list of changesets (typically from an Rx Buffer operation) into a single changeset + /// by concatenating all changes. Empty buffers are filtered out. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change sets. + /// The source observable of buffered changeset lists. + /// An observable changeset combining all changes from each buffer into a single emission. + /// is null. public static IObservable> FlattenBufferResult(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -1702,13 +1876,29 @@ public static IObservable> FlattenBufferResult - /// Provides a call back for each change. + /// Invokes for every individual in each changeset, + /// regardless of change reason. The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source. - /// The action. - /// An observable which will perform the action on each item. + /// The source changeset stream. + /// The action to invoke for each change. Receives the full struct, including , , , and . + /// A stream that forwards all changesets from unchanged. + /// + /// + /// All change reasons (Add, Update, Remove, Refresh) trigger the callback. + /// Use , + /// , + /// , or + /// + /// to target a specific reason. + /// + /// + /// Implemented via Rx's Do operator on the changeset stream. + /// Exceptions thrown in propagate as OnError to the subscriber. No try-catch is applied. + /// + /// + /// or is null. public static IObservable> ForEachChange(this IObservable> source, Action> action) where TObject : notnull where TKey : notnull @@ -1719,20 +1909,12 @@ public static IObservable> ForEachChange changes.ForEach(action)); } - /// - /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. - /// This is the equivalent of SQL full join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1749,19 +1931,48 @@ public static IObservable> FullJoin - /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. - /// This is the equivalent of SQL full join. + /// Joins two changeset streams, producing a result for every key that appears on either side (or both). + /// Both sides are because a given key may only exist on one side at any point. + /// Equivalent to SQL FULL OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddEmits with the left value and the matching right (or Optional.None if no right exists). + /// UpdateRe-invokes with the new left value and current right (if any). + /// RemoveIf a right match still exists, re-invokes the selector with left as Optional.None. If neither side remains, removes the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddEmits with the matching left (or Optional.None) and the right value. + /// UpdateRe-invokes selector with current left (if any) and the new right value. + /// RemoveIf a left match still exists, re-invokes the selector with right as Optional.None. If neither side remains, removes the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1777,20 +1988,12 @@ public static IObservable> FullJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. - /// This is the equivalent of SQL full join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1807,19 +2010,49 @@ public static IObservable> FullJoinMany - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. - /// This is the equivalent of SQL full join. + /// Groups right-side items by their mapped key, then full-joins each group to the left source. + /// A result is produced for every key that appears on either side (or both). The left value is + /// because only the right side may have entries for a given key. + /// Equivalent to SQL FULL OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddEmits with the left value and the current right group for that key (may be empty). + /// UpdateRe-invokes with the new left value and current right group. + /// RemoveIf the right group is non-empty, re-invokes with left as Optional.None. If both sides are empty, removes the result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group, then re-invokes selector with the current left (if any) and the updated group. + /// UpdateUpdates the right group and re-invokes selector. + /// RemoveUpdates the right group. If the group becomes empty and no left exists, removes the result. Otherwise re-invokes selector. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1836,13 +2069,13 @@ public static IObservable> FullJoinMany - /// Groups the source on the value returned by group selector factory. - /// A group is included for each item in the resulting group source. + /// Groups items from the source changeset, producing groups only for group keys present in . + /// Useful for parent-child relationships where parents and children come from different streams. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. + /// The source changeset stream. /// The group selector factory. /// /// A distinct stream used to determine the result. @@ -1864,14 +2097,38 @@ public static IObservable> Group - /// Groups the source on the value returned by group selector factory. + /// Groups items from the source changeset by a key extracted via . + /// Each group is an observable sub-cache that receives changes for its members. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. - /// The group selector key. - /// An observable which will emit group change sets. + /// The source changeset stream. + /// Extracts the group key from each item. + /// An observable that emits group changesets. Each group exposes a sub-cache of its members. + /// + /// + /// Items are assigned to groups based on the value returned by . + /// Groups are created on demand when the first item is assigned, and removed when their last member is removed. + /// + /// + /// EventBehavior + /// AddThe group key is evaluated. The item is added to the corresponding group (creating the group if new). An Add is emitted to the group's sub-cache. + /// UpdateThe group key is re-evaluated. If unchanged, an Update is emitted within the same group. If the key changed, the item is removed from the old group (emitting Remove) and added to the new group (emitting Add). An empty old group is removed. + /// RemoveThe item is removed from its group. If the group becomes empty, the group itself is removed from the output. + /// RefreshThe group key is re-evaluated. If unchanged, a Refresh is forwarded within the group. If the key changed, the item moves between groups (Remove from old, Add to new). + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// Worth noting: Each group is a live sub-cache that can be subscribed to independently. Subscribers + /// to a group receive only changes for items in that group. When a group is removed (becomes empty), + /// its sub-cache completes. + /// + /// + /// + /// + /// public static IObservable> Group(this IObservable> source, Func groupSelectorKey) where TObject : notnull where TKey : notnull @@ -1883,23 +2140,12 @@ public static IObservable> Group(source, groupSelectorKey, null).Run(); } - /// - /// Groups the source on the value returned by group selector factory. - /// - /// The type of the object. - /// The type of the key. - /// The type of the group key. - /// The source. - /// The group selector key. - /// Invoke to the for the grouping to be re-evaluated. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// + /// The source changeset stream. + /// Extracts the group key from each item. + /// When this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. + /// An observable that emits group changesets. + /// This overload adds a signal. When it fires, every item in the cache is re-grouped using the current selector, which is useful when the grouping depends on mutable item state. public static IObservable> Group(this IObservable> source, Func groupSelectorKey, IObservable regrouper) where TObject : notnull where TKey : notnull @@ -1913,22 +2159,34 @@ public static IObservable> Group - /// Groups the source on the value returned by the latest value from the group selector factory observable. + /// Groups items using a dynamically changing group selector function. + /// Each time emits a new selector, all items are re-grouped. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. - /// The group selector key observable. - /// Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// The source changeset stream. + /// An observable that emits group selector functions. Each emission triggers a full re-grouping of all items. + /// Optional signal to force re-evaluation of all items against the current selector. + /// An observable that emits group changesets. + /// + /// + /// Unlike the static-selector overload, this accepts an observable of selector functions. When a new selector + /// arrives, every item is re-evaluated and may move between groups. The optional + /// signal triggers re-evaluation without changing the selector (useful when item properties that affect grouping change). + /// + /// + /// EventBehavior + /// AddThe current selector determines the group. Item is added to the group (group created if new). + /// UpdateGroup key re-evaluated. Item may move between groups if the key changed. + /// RemoveItem removed from its group. Empty groups are removed. + /// RefreshGroup key re-evaluated. Item may move between groups. + /// OnErrorForwarded from source or from . + /// OnCompletedForwarded when the source completes. + /// + /// + /// + /// public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -1940,23 +2198,11 @@ public static IObservable> Group(source, groupSelectorKeyObservable, regrouper).Run(); } - /// - /// Groups the source on the value returned by the latest value from the group selector factory observable. - /// - /// The type of the object. - /// The type of the key. - /// The type of the group key. - /// The source. - /// The group selector key observable. - /// Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// + /// The source changeset stream. + /// An observable of selector functions that take only the item (not the key). + /// Optional signal to force re-evaluation. + /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -1973,9 +2219,12 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source. + /// The source changeset stream. /// The group selector key. /// An observable which will emit group change sets. + /// + /// Worth noting: Items do not appear in any group until their per-item observable emits the first group key. Per-item observable errors terminate the entire stream. + /// public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull where TKey : notnull @@ -1993,7 +2242,7 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. + /// The source changeset stream. /// The group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) @@ -2013,7 +2262,7 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. + /// The source changeset stream. /// The property selector used to group the items. /// A time span that indicates the throttle to wait for property change events. /// The scheduler. @@ -2036,7 +2285,7 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. + /// The source changeset stream. /// The property selector used to group the items. /// A time span that indicates the throttle to wait for property change events. /// The scheduler. @@ -2053,22 +2302,35 @@ public static IObservable> Gr } /// - /// Groups the source on the value returned by group selector factory. Each update produces immutable grouping. + /// Groups items by , emitting immutable group snapshots instead of mutable sub-caches. + /// Each group change contains a frozen copy of the group's state at that point in time. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source. - /// The group selector key. - /// Invoke to the for the grouping to be re-evaluated. - /// An observable which will emit immutable group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// The source changeset stream. + /// Extracts the group key from each item. + /// Optional signal to force re-evaluation of all items against the group selector. + /// An observable that emits immutable group changesets. + /// + /// + /// Behaves identically to + /// in terms of how items are assigned to groups, but each group emission is an immutable snapshot. + /// This makes it safe for parallel processing and eliminates race conditions on group state. + /// The tradeoff is higher memory usage, since each change produces a new snapshot of the affected group. + /// + /// + /// EventBehavior + /// AddItem added to its group. An immutable snapshot of the group is emitted. + /// UpdateIf group key unchanged, group snapshot re-emitted. If changed, item moves between groups; both affected groups emit new snapshots. + /// RemoveItem removed from group. Updated snapshot emitted. Empty groups are removed. + /// RefreshGroup key re-evaluated. If changed, item moves; affected group snapshots emitted. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// + /// public static IObservable> GroupWithImmutableState(this IObservable> source, Func groupSelectorKey, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -2097,7 +2359,7 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) @@ -2124,7 +2386,7 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) @@ -2142,20 +2404,12 @@ public static IObservable> IncludeUpdateWhen - /// Joins the left and right observable data sources, taking values when both left and right values are present - /// This is the equivalent of SQL inner join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left and right values into a destination object. The composite key is not provided in this overload. + /// Overload that omits the composite key from the result selector. Delegates to . public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2172,19 +2426,48 @@ public static IObservable> IncludeUpdateWhen - /// Groups the right data source and joins the to the left and the right sources, taking values when both left and right values are present - /// This is the equivalent of SQL inner join. + /// Joins two changeset streams, producing a result only for keys that exist on both sides simultaneously. + /// When either side loses its value for a key, the joined result is removed. Equivalent to SQL INNER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). + /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a matching right value exists, invokes and emits an Add. If no right match, no emission. + /// UpdateIf a matching right exists, re-invokes the selector and emits an Update. + /// RemoveRemoves all joined results involving the removed left key. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddIf a matching left value exists, invokes the selector and emits an Add. + /// UpdateIf a matching left exists, re-invokes the selector and emits an Update. + /// RemoveRemoves the joined result for this right key (if it was downstream). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// The output is keyed by a (TLeftKey, TRightKey) composite tuple, since a single left item may match multiple right items. + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func<(TLeftKey leftKey, TRightKey rightKey), TLeft, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2200,20 +2483,12 @@ public static IObservable> IncludeUpdateWhen(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. - /// This is the equivalent of SQL inner join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2230,19 +2505,48 @@ public static IObservable> InnerJoinMany - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. - /// This is the equivalent of SQL inner join. + /// Groups right-side items by their mapped key, then inner-joins each group to the left source. + /// A result is produced only when a left item and at least one right item share the same key. + /// Equivalent to SQL INNER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a non-empty right group exists for this key, invokes and emits an Add. Otherwise no emission. + /// UpdateIf a right group exists, re-invokes the selector and emits an Update. + /// RemoveRemoves the joined result (if it was downstream). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If a matching left exists and the group was previously empty, emits an Add. If already joined, emits an Update. + /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. + /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2259,29 +2563,34 @@ public static IObservable> InnerJoinMany - /// Invokes Refresh method for an object which implements IEvaluateAware. + /// Calls Evaluate() on items that implement when a Refresh change arrives. + /// Other change reasons are forwarded without invoking Evaluate. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change sets. + /// The source changeset stream. + /// An observable that emits the same changesets as , unchanged. + /// + /// + /// EventBehavior + /// AddForwarded unchanged. + /// UpdateForwarded unchanged. + /// RemoveForwarded unchanged. + /// RefreshCalls Evaluate() on the item, then forwards the change. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// public static IObservable> InvokeEvaluate(this IObservable> source) where TObject : IEvaluateAware where TKey : notnull => source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); - /// - /// Joins the left and right observable data sources, taking all left values and combining any matching right values. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the optional right into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2298,18 +2607,48 @@ public static IObservable> LeftJoin - /// Joins the left and right observable data sources, taking all left values and combining any matching right values. + /// Joins two changeset streams, producing a result for every left-side key. The right side is + /// because a matching right item may or may not exist. All left items + /// appear in the output regardless. Equivalent to SQL LEFT OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the left value and matching right (or Optional.None). + /// UpdateRe-invokes the selector with the new left value and current right (if any). + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddIf a matching left exists, re-invokes the selector (right transitions from None to Some) and emits an Update. + /// UpdateIf a matching left exists, re-invokes the selector with the new right value. + /// RemoveIf a matching left exists, re-invokes the selector (right transitions from Some to None) and emits an Update. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2325,20 +2664,12 @@ public static IObservable> LeftJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. - /// This is the equivalent of SQL left join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2355,19 +2686,48 @@ public static IObservable> LeftJoinMany - /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. - /// This is the equivalent of SQL left join. + /// Groups right-side items by their mapped key, then left-joins each group to the left source. + /// A result is produced for every left-side key. The right group may be empty if no right items match. + /// Equivalent to SQL LEFT OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the left value and the current right group (which may be empty). + /// UpdateRe-invokes the selector with the new left value and current right group. + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If a matching left exists, re-invokes the selector and emits an Update. + /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. + /// RemoveUpdates the right group. If a matching left exists, re-invokes the selector (group may now be empty). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2384,16 +2744,27 @@ public static IObservable> LeftJoinMany - /// Applies a size limiter to the number of records which can be included in the - /// underlying cache. When the size limit is reached the oldest items are removed. + /// Applies a FIFO size limit to the changeset stream. When the number of items exceeds , + /// the oldest items are evicted and emitted as Remove changes. /// /// The type of the object. /// The type of the key. - /// The source. - /// The size. - /// An observable which emits change sets. - /// source. - /// size cannot be zero. + /// The source changeset stream. + /// The maximum number of items allowed. Must be greater than zero. + /// An observable changeset stream with size-limited contents. + /// + /// + /// EventBehavior + /// AddForwarded. If the cache exceeds the size limit, the oldest items are emitted as Remove changes. + /// UpdateForwarded unchanged. + /// RemoveForwarded unchanged. + /// RefreshForwarded unchanged. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// + /// is null. + /// is zero or negative. public static IObservable> LimitSizeTo(this IObservable> source, int size) where TObject : notnull where TKey : notnull @@ -2409,17 +2780,17 @@ public static IObservable> LimitSizeTo( } /// - /// Limits the number of records in the cache to the size specified. When the size is reached - /// the oldest items are removed from the cache. + /// Operates directly on a , removing the oldest items when the cache + /// exceeds . Returns an observable of the evicted key-value pairs (not a changeset stream). /// /// The type of the object. /// The type of the key. - /// The source. - /// The size limit. - /// The scheduler. - /// An observable which emits the key value pairs. - /// source. - /// Size limit must be greater than zero. + /// The source cache to apply the size limit to. + /// The maximum number of items allowed. Must be greater than zero. + /// Optional scheduler for observing changes. Defaults to . + /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. + /// is null. + /// is zero or negative. public static IObservable>> LimitSizeTo(this ISourceCache source, int sizeLimit, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -2454,18 +2825,38 @@ public static IObservable>> LimitSizeTo< } /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. + /// Subscribes to a child observable for each item in the source cache changeset stream and merges all child + /// emissions into a single . When an item is added, + /// creates its child subscription. When updated, the previous child subscription is disposed and a new one is created. + /// When removed, its child subscription is disposed. Refresh changes have no effect on subscriptions. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source. - /// The observable selector. - /// An observable which emits the transformed value. - /// source - /// or - /// observableSelector. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of values emitted by child observables. + /// The source cache changeset stream. + /// Factory function that produces a child observable for each source item. + /// An observable that emits values from all active child observables, interleaved by arrival order. + /// + /// + /// This operator does not produce changesets. It produces a flat stream of + /// values, similar to Rx SelectMany but lifecycle-aware: child subscriptions track items entering and + /// leaving the source cache. + /// + /// + /// EventBehavior + /// AddCalls to create a child observable and subscribes to it. Emissions from the child flow into the merged output. + /// UpdateDisposes the previous child subscription and creates a new one for the updated item. + /// RemoveDisposes the child subscription for the removed item. + /// RefreshNo effect on subscriptions. The child observable continues unchanged. + /// OnErrorErrors from child observables are silently swallowed (the child is unsubscribed). Errors from the source changeset stream terminate the merged output. + /// OnCompletedThe output completes only when the source completes and all active child observables have also completed. + /// + /// Worth noting: The output is a plain IObservable<TDestination>, not a changeset stream. If you need merged changesets, use instead. + /// + /// or is null. + /// + /// + /// public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2476,19 +2867,9 @@ public static IObservable MergeMany(t return new MergeMany(source, observableSelector).Run(); } - /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source. - /// The observable selector. - /// An observable which emits the transformed value. - /// source - /// or - /// observableSelector. + /// + /// The source cache changeset stream. + /// Factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2500,13 +2881,41 @@ public static IObservable MergeMany(t } /// - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges multiple changeset streams that arrive dynamically into a single unified changeset stream. + /// Each inner stream emitted by the outer observable is subscribed and its changes forwarded downstream. + /// When multiple sources provide the same key, the first source to add it retains priority unless a + /// comparer-based overload is used. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// A unified changeset stream containing changes from all active source streams. + /// + /// + /// Each inner changeset stream is independently tracked. When multiple sources provide the same key, + /// this overload uses first-in-wins semantics: the value from whichever source added the key first is + /// the one published downstream. To control which value wins for duplicate keys, use an overload that + /// accepts an , which selects the lowest-ordered value across all sources. + /// + /// + /// EventBehavior + /// AddIf no source has previously provided this key, an Add is emitted downstream. If another source already holds this key, the new value is tracked internally but not emitted (first-in-wins). With a comparer, the lowest-ordered value across all sources is selected and published instead. + /// UpdateIf the updating source currently owns the downstream value for this key, an Update is emitted. If a comparer is provided and the update causes a different source's value to become the best candidate, an Update is emitted with that other source's value. + /// RemoveIf the removed value was the one published downstream, the operator scans all remaining sources for the same key. If another source still holds that key, an Update is emitted with the replacement value (selected by comparer if provided, otherwise the next available). If no other source holds the key, a Remove is emitted. + /// RefreshIf the refreshed item matches the currently published value, the Refresh is forwarded. With a comparer, all sources are re-evaluated first; if a different value now wins, an Update is emitted instead of the Refresh. + /// OnErrorAn error from any source (outer or inner) terminates the entire merged output. + /// OnCompletedThe output completes when the outer observable completes and all subscribed inner observables have also completed. + /// + /// + /// Worth noting: When a source removes a key that was published downstream, the fallback to another + /// source's value is emitted as an Update (not an Add). This can be surprising if you expect + /// a Remove followed by an Add. Also, errors from any single inner source terminate the entire merged + /// stream, so consider error handling within individual sources if isolation is needed. + /// + /// + /// is null. + /// + /// public static IObservable> MergeChangeSets(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -2517,14 +2926,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using a comparer to resolve key conflicts. + /// When multiple sources provide the same key, the item ordering lowest according to + /// is published downstream. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// A unified changeset stream containing changes from all active source streams. + /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2536,14 +2947,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using an equality comparer to suppress + /// redundant updates. When an incoming value for a key is equal (per ) + /// to the currently published value, the update is suppressed. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// A unified changeset stream containing changes from all active source streams. + /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -2555,15 +2968,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using both a comparer for key conflict resolution + /// and an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// A unified changeset stream containing changes from all active source streams. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2576,16 +2990,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams into a single output. + /// Uses first-in-wins semantics for key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSet. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2597,17 +3012,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using a comparer for key conflict resolution. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSet. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Comparer to determine which value wins when both sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2620,17 +3035,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSet. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2643,18 +3058,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using both a comparer and an equality comparer. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSet. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Comparer to determine which value wins when both sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2668,16 +3083,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams into a single output. + /// Uses first-in-wins semantics for key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2689,17 +3105,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using a comparer for key conflict resolution. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSets. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Comparer to determine which value wins when multiple sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2712,17 +3128,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSets. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2735,18 +3151,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using both a comparer and an equality comparer. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// The Other Observable ChangeSets. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Comparer to determine which value wins when multiple sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2760,15 +3176,27 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single unified output. All source streams are + /// subscribed when the output observable is subscribed to. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// + /// + /// When multiple sources provide items with the same key, this overload uses first-in-wins semantics: + /// the first source to provide a key retains priority. Removing that source's item allows the next + /// available value for that key (if any) to surface. To control which value wins, use an overload + /// that accepts an . + /// + /// + /// An error from any source terminates the entire merged output. + /// + /// + /// is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2779,16 +3207,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using a comparer for key conflict + /// resolution. When multiple sources provide the same key, the item ordering lowest according to + /// is published downstream. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2800,16 +3230,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using an equality comparer to + /// suppress redundant updates. When an incoming value for a key is equal (per ) + /// to the currently published value, the update is suppressed. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2821,17 +3253,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using both a comparer for key + /// conflict resolution and an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// , , or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2844,17 +3277,19 @@ public static IObservable> MergeChangeSets - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. + /// The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2867,17 +3302,18 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2892,18 +3328,19 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -2917,18 +3354,38 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream produced by + /// and merges all child changes into a single flattened output stream. + /// Child subscriptions follow the source item lifecycle: created on Add, replaced on Update (the old + /// subscription is disposed), and disposed on Remove (emitting Removes for all of that item's children). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// + /// + /// Unlike , + /// errors from child changeset streams propagate to the output (they are not silently swallowed). + /// An error from the source or any child terminates the merged output. + /// + /// + /// EventBehavior + /// AddSubscribes to the child changeset stream for the new source item. All changes from the child are merged into the output. + /// UpdateDisposes the old child subscription, subscribes to a new child stream for the updated item. Items from the old child are removed from the output. + /// RemoveDisposes the child subscription. All items contributed by that child are emitted as Remove changes in the output. + /// RefreshNo effect on child subscriptions. + /// OnErrorErrors from child changeset streams propagate and terminate the output (unlike MergeMany which swallows child errors). + /// OnCompletedCompletes when the source completes and all active child streams have also completed. + /// + /// Worth noting: When multiple children produce items with the same destination key, the determines which value wins. Without a comparer, first-in-wins. The suppresses no-op updates when the new value equals the current one. + /// + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -2942,19 +3399,21 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required . + /// Uses to resolve destination key conflicts by source priority. + /// The selector receives only the item, not its key. + /// Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -2968,19 +3427,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required . + /// Uses to resolve destination key conflicts by source priority. + /// Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -2988,20 +3448,20 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets with a required and + /// explicit control. The selector receives only the item. + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3015,20 +3475,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required and + /// explicit control. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3036,20 +3496,21 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, resortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets. Uses to resolve + /// destination key conflicts. The selector receives only the item, not its key. + /// Source priorities are always re-evaluated on Refresh (default behavior). + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3063,20 +3524,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets. Uses to resolve + /// destination key conflicts. Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3084,21 +3545,21 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets with full control over all conflict resolution parameters. + /// The selector receives only the item, not its key. + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3112,21 +3573,33 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child + /// changes into a single flattened output. When multiple source items produce children with the same destination key, + /// determines which source has priority (the source ordering lower wins). + /// If sources compare equal, (if provided) breaks the tie. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// Optional fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. + /// + /// + /// The provides a layer of conflict resolution above the child values themselves. + /// This is useful when source items represent priority tiers (e.g., user settings overriding defaults). + /// + /// + /// Errors from child streams propagate to the output. An error from the source or any child terminates the merged output. + /// The output completes when the source completes and all active child streams have also completed. + /// + /// + /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3141,15 +3614,17 @@ public static IObservable> MergeManyCh } /// - /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. + /// For each item in the source cache, subscribes to a child list changeset stream produced by + /// and merges all child changes into a single flattened list changeset output. + /// Child subscriptions follow the source item lifecycle: created on Add, replaced on Update, disposed on Remove. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// The result from merging the child changesets together. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child list changeset streams. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child list changeset stream. + /// Optional equality comparer to detect duplicate items in the merged list output. + /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3162,15 +3637,16 @@ public static IObservable> MergeManyChangeSets - /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. + /// For each item in the source cache, subscribes to a child list changeset stream and merges all child changes + /// into a single flattened list changeset output. The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The Source Observable ChangeSet. - /// Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// The result from merging the child changesets together. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child list changeset streams. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child list changeset stream. + /// Optional equality comparer to detect duplicate items in the merged list output. + /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3181,18 +3657,17 @@ public static IObservable> MergeManyChangeSets - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. + /// Like , + /// but wraps each emitted value as an , pairing the source item + /// with the value it produced. This lets you identify which source item is responsible for each emission. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source. - /// The observable selector. - /// An observable which emits the item with the value. - /// source - /// or - /// observableSelector. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of values emitted by child observables. + /// The source cache changeset stream. + /// Factory function that produces a child observable for each source item. + /// An observable of pairing each emission with its source item. + /// or is null. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3203,19 +3678,9 @@ public static IObservable> MergeManyItems(source, observableSelector).Run(); } - /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source. - /// The observable selector. - /// An observable which emits the item with the value. - /// source - /// or - /// observableSelector. + /// + /// The source cache changeset stream. + /// Factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3227,22 +3692,26 @@ public static IObservable> MergeManyItems - /// Monitors the status of a stream. + /// Monitors the source observable and emits values: Pending initially, + /// Loaded when the first value arrives, Errored on error, and Completed on completion. + /// This is not a changeset operator. /// /// The type of the source observable. - /// The source. - /// An observable which monitors the status of the observable. - /// source. + /// The source observable to monitor. + /// An observable that emits values reflecting the source's lifecycle. + /// is null. + /// public static IObservable MonitorStatus(this IObservable source) => new StatusMonitor(source).Run(); /// - /// Suppresses updates which are empty. + /// Filters out empty changesets from the stream. A thin wrapper around Where(changes => changes.Count != 0). /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change set values when not empty. - /// source. + /// The source changeset stream. + /// An observable that emits only non-empty changesets. + /// is null. + /// public static IObservable> NotEmpty(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3253,16 +3722,27 @@ public static IObservable> NotEmpty(thi } /// - /// Filters an observable changeset so that it only includes items that are of type . + /// Filters and casts items in the changeset to . Items that are not of type + /// are excluded. Combines filter and transform in one step without an intermediate cache. /// /// The type of the objects in the source changeset. /// The type of the key. - /// The type of the objects that are allowed to pass the filter. - /// The source observable changeset of instances. - /// Indicates whether or not to suppress changesets that end up being empty after the conversion. - /// An observable changeset of where each item was either converted from or filtered out. - /// source. - /// Combines a filter and a transform into a single step that does not use an intermediate cache. + /// The destination type to filter and cast to. + /// The source observable changeset. + /// If true, changesets that become empty after filtering are suppressed. + /// An observable changeset of items. + /// + /// + /// EventBehavior + /// AddIf the item is , cast and emit as Add. Otherwise dropped. + /// UpdateRe-evaluated. If the new item is , emit accordingly. If the old item was downstream but the new one is not, emit Remove. + /// RemoveIf the item was downstream, emit Remove. + /// RefreshIf the item is downstream, forwarded as Refresh. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// + /// is null. public static IObservable> OfType(this IObservable> source, bool suppressEmptyChangeSets = true) where TObject : notnull where TKey : notnull @@ -3278,9 +3758,28 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source. - /// The add action that takes the new value and the associated key. - /// An observable which emits a change set with items being added. + /// The source changeset stream. + /// The callback invoked for each added item. Receives the new item and its key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddInvokes with the item and key. + /// UpdateIgnored. + /// RemoveIgnored. + /// RefreshIgnored. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3291,15 +3790,10 @@ public static IObservable> OnItemAdded( return source.OnChangeAction(ChangeReason.Add, addAction); } - /// - /// Callback for each item as and when it is being added to the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The add action that takes the new value. - /// An observable which emits a change set with items being added. - /// Overload for with a callback that doesn't use a key. + /// + /// The source changeset stream. + /// The callback invoked for each added item. Receives only the item (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3310,9 +3804,26 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source. - /// The refresh action that takes the refreshed value and the key. - /// An observable which emits a change set with items being added. + /// The source changeset stream. + /// The callback invoked for each refreshed item. Receives the item and its key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored. + /// UpdateIgnored. + /// RemoveIgnored. + /// RefreshInvokes with the item and key. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull @@ -3323,34 +3834,54 @@ public static IObservable> OnItemRefreshed - /// Callback for each item as and when it is being refreshed in the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The refresh action that takes the refreshed value. - /// An observable which emits a change set with items being added. - /// Overload for with a callback that doesn't use a key. + /// + /// The source changeset stream. + /// The callback invoked for each refreshed item. Receives only the item (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull => source.OnItemRefreshed((obj, _) => refreshAction(obj)); /// - /// Callback for each item/key as and when it is being removed from the stream. + /// Invokes for each item with in the changeset stream. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source. - /// The remove action that takes the removed value and the key. - /// Should the remove action be invoked when the subscription is disposed. - /// An observable which emits a change set with items being removed. - /// - /// source - /// or - /// removeAction. - /// + /// The source changeset stream. + /// The callback invoked for each removed item. Receives the removed item and its key. + /// + /// When true (the default), the callback is also invoked for every item still in the cache + /// when the subscription is disposed. When false, only inline Remove changes trigger the callback. + /// + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored (but tracked internally when is true). + /// UpdateIgnored (cache updated internally when is true). + /// RemoveInvokes with the item and key. + /// RefreshIgnored. + /// + /// + /// + /// Unsubscribe behavior: when is true, the operator + /// maintains an internal cache mirroring the stream. On disposal, it iterates all remaining items and + /// invokes for each. This is useful for cleanup logic (e.g. event unsubscription) + /// that must run for items that were never explicitly removed. + /// + /// + /// Exceptions thrown in propagate as OnError during inline removes. + /// During unsubscribe disposal, exceptions are not caught. + /// + /// Worth noting: The action also fires for ALL remaining items when the subscription is disposed (unless invokeOnUnsubscribe is false). The action runs under a lock; avoid calling into other caches from within it. + /// + /// or is null. + /// + /// public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull @@ -3366,34 +3897,43 @@ public static IObservable> OnItemRemoved - /// Callback for each item as and when it is being removed from the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The remove action that takes the removed value. - /// Should the remove action be invoked when the subscription is disposed. - /// An observable which emits a change set with items being removed. - /// - /// source - /// or - /// removeAction. - /// - /// Overload for with a callback that doesn't use the key. + /// + /// The source changeset stream. + /// The callback invoked for each removed item. Receives only the item (no key). + /// When true (the default), also invoked for all remaining items on disposal. + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull => source.OnItemRemoved((obj, _) => removeAction(obj), invokeOnUnsubscribe); /// - /// Callback when an item has been updated eg. (current, previous)=>{}. + /// Invokes for each item with in the changeset stream. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source. - /// The update action that takes current value, previous value, and the key. - /// An observable which emits a change set with items being updated. + /// The source changeset stream. + /// The callback invoked for each updated item. Receives the current value, previous value, and key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored. + /// UpdateInvokes with (current, previous, key). The previous value is always available for Update changes. + /// RemoveIgnored. + /// RefreshIgnored. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// + /// public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull @@ -3404,33 +3944,43 @@ public static IObservable> OnItemUpdated change.Reason == ChangeReason.Update, change => updateAction(change.Current, change.Previous.Value, change.Key)); } - /// - /// Callback when an item has been updated eg. (current, previous)=>{}. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The update action that takes the current value and previous value. - /// An observable which emits a change set with items being updated. - /// Overload for with a callback that doesn't use the key. + /// + /// The source changeset stream. + /// The callback invoked for each updated item. Receives only the current and previous values (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull => source.OnItemUpdated((cur, prev, _) => updateAction(cur, prev)); /// - /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. + /// Combines multiple changeset streams using logical OR (union). An item appears downstream if it exists in any source. /// /// The type of the object. /// The type of the key. - /// The source. - /// The others. - /// An observable which emits change sets. - /// - /// source - /// or - /// others. - /// + /// The first source changeset stream. + /// Additional changeset streams to combine with. + /// A changeset stream containing items present in any of the sources. + /// + /// + /// Items are tracked via reference counting across all sources. An item appears downstream as long as + /// at least one source contains it. When the last source holding a key removes it, the item is removed downstream. + /// + /// + /// EventBehavior + /// AddIf this is the first source to provide the key, an Add is emitted. If other sources already have the key, the reference count is incremented but no emission occurs. + /// UpdateIf the item is currently downstream, an Update is emitted. + /// RemoveReference count decremented. If the count reaches zero (no source holds the key), a Remove is emitted. Otherwise no emission. + /// RefreshIf the item is downstream, a Refresh is forwarded. + /// OnErrorAn error from any source terminates the combined output. + /// OnCompletedThe output completes when all sources have completed. + /// + /// + /// or is null. + /// + /// + /// + /// public static IObservable> Or(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -3445,18 +3995,9 @@ public static IObservable> Or(this IObs return source.Combine(CombineOperator.Or, others); } - /// - /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable which emits change sets. - /// - /// source - /// or - /// others. - /// + /// + /// A fixed collection of changeset streams to combine. + /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Or(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -3472,7 +4013,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -3489,7 +4030,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -3506,7 +4047,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -3518,18 +4059,19 @@ public static IObservable> Or(this IObs } /// - /// Populate a cache from an observable stream. + /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted batch of items. /// /// The type of the object. /// The type of the key. - /// The source. - /// The observable. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// keySelector. - /// + /// The source cache to populate. + /// The observable that emits batches of items. + /// An that, when disposed, unsubscribes from . + /// + /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. + /// + /// or is null. + /// + /// public static IDisposable PopulateFrom(this ISourceCache source, IObservable> observable) where TObject : notnull where TKey : notnull @@ -3540,18 +4082,14 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Populate a cache from an observable stream. + /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted item. /// /// The type of the object. /// The type of the key. - /// The source. - /// The observable. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// keySelector. - /// + /// The source cache to populate. + /// The observable that emits individual items. + /// An that, when disposed, unsubscribes from . + /// or is null. public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) where TObject : notnull where TKey : notnull @@ -3562,18 +4100,30 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Populates a source into the specified cache. + /// Subscribes to the changeset stream and clones each changeset into the destination cache. /// /// The type of the object. /// The type of the key. - /// The source. - /// The destination. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// destination. - /// + /// The source changeset stream. + /// The destination cache to populate. + /// An that, when disposed, unsubscribes from the source. + /// + /// + /// Each changeset from the source is applied to the destination cache inside an Edit call. + /// + /// + /// EventBehavior + /// AddThe item is added to the destination cache via AddOrUpdate. + /// UpdateThe item is updated in the destination cache via AddOrUpdate. + /// RemoveThe item is removed from the destination cache. + /// RefreshA Refresh is issued on the destination cache for the item. + /// OnErrorThe subscription is terminated. The destination cache is not rolled back. + /// OnCompletedThe subscription ends. The destination cache retains all items. + /// + /// + /// or is null. + /// + /// public static IDisposable PopulateInto(this IObservable> source, ISourceCache destination) where TObject : notnull where TKey : notnull @@ -3584,17 +4134,10 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// Populates a source into the specified cache. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The destination. - /// A disposable which will unsubscribe from the source. - /// source - /// or - /// destination. + /// + /// The source changeset stream. + /// The destination intermediate cache to populate. + /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) where TObject : notnull where TKey : notnull @@ -3605,14 +4148,10 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// Populates a source into the specified cache. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The destination. - /// A disposable which will unsubscribe from the source. + /// + /// The source changeset stream. + /// The destination lock-free cache to populate. + /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) where TObject : notnull where TKey : notnull @@ -3624,19 +4163,30 @@ public static IDisposable PopulateInto(this IObservable - /// The latest copy of the cache is exposed for querying after each modification to the underlying data. + /// Projects the current cache state through after each modification. + /// Emits a new value of on every changeset. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source. - /// The result selector. - /// An observable which emits the destination values. - /// - /// source - /// or - /// resultSelector. - /// + /// The source changeset stream. + /// Projects the current snapshot to a result value. + /// An observable that emits a projected value after each changeset. + /// + /// + /// EventBehavior + /// AddCache updated, then invoked and result emitted. + /// UpdateCache updated, then invoked and result emitted. + /// RemoveCache updated, then invoked and result emitted. + /// RefreshCache updated, then invoked and result emitted. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: The selector is called on every changeset, which can be chatty. The exposes the full cache state for LINQ-style queries. + /// + /// or is null. + /// + /// public static IObservable QueryWhenChanged(this IObservable> source, Func, TDestination> resultSelector) where TObject : notnull where TKey : notnull @@ -3652,7 +4202,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -3670,7 +4220,7 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// The source. + /// The source changeset stream. /// Should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. @@ -3685,12 +4235,14 @@ public static IObservable> QueryWhenChanged - /// Cache equivalent to Publish().RefCount(). The source is cached so long as there is at least 1 subscriber. + /// Cache-aware equivalent of Publish().RefCount(). An internal cache is created on the first subscriber + /// and disposed when the last subscriber unsubscribes. All subscribers share the same upstream subscription. /// /// The type of the object. - /// The type of the destination key. - /// The source. - /// An observable which emits change sets that are ref counted. + /// The type of the key. + /// The source changeset stream. + /// A ref-counted observable changeset stream. + /// public static IObservable> RefCount(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3701,13 +4253,23 @@ public static IObservable> RefCount(thi } /// - /// Signal observers to re-evaluate the specified item. + /// Signals downstream operators to re-evaluate the specified item. Produces a changeset with a single Refresh change. /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to refresh. + /// + /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. + /// + /// EventBehavior + /// RefreshProduced for the specified item. Downstream operators re-evaluate this item against their current logic (filter predicate, sort comparer, group key selector, etc.). + /// OtherNo Add, Update, or Remove events are produced by this method. + /// + /// + /// is null. + /// + /// public static void Refresh(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -3718,13 +4280,13 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signal observers to re-evaluate the specified items. + /// Signals downstream operators to re-evaluate the specified items. Produces one changeset with a Refresh for each item. /// /// The type of the object. /// The type of the key. - /// The source. - /// The items. - /// source. + /// The source cache. + /// The items to refresh. + /// is null. public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -3735,12 +4297,12 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signal observers to re-evaluate the all items. + /// Signals downstream operators to re-evaluate all items in the cache. Produces one changeset with a Refresh for every item. /// /// The type of the object. /// The type of the key. - /// The source. - /// source. + /// The source cache. + /// is null. public static void Refresh(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -3751,14 +4313,24 @@ public static void Refresh(this ISourceCache sourc } /// - /// Removes the specified item from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes the specified item from the cache. Produces a Remove changeset if the item exists, nothing otherwise. /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to remove. + /// + /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. + /// + /// EventBehavior + /// RemoveProduced if the key exists in the cache. The removed value is included in the changeset. + /// OtherNo Add, Update, or Refresh events are produced by this method. + /// + /// + /// is null. + /// + /// + /// public static void Remove(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -3769,14 +4341,13 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes the item with the specified key from the cache. Produces a Remove changeset if the key exists, nothing otherwise. /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// source. + /// The source cache. + /// The key of the item to remove. + /// is null. public static void Remove(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3787,14 +4358,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified items from the cache. - /// Any items not contained in the cache are ignored. + /// Removes the specified items from the cache. Any items not present in the cache are ignored. + /// Produces a Remove changeset for each item that existed. /// /// The type of the object. /// The type of the key. - /// The source. - /// The items. - /// source. + /// The source cache. + /// The items to remove. + /// is null. public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -3805,14 +4376,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. + /// Removes the items with the specified keys from the cache. Any keys not present are ignored. + /// Produces a Remove changeset for each key that existed. /// /// The type of the object. /// The type of the key. - /// The source. - /// The keys. - /// source. + /// The source cache. + /// The keys to remove. + /// is null. public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3822,15 +4393,10 @@ public static void Remove(this ISourceCache source source.Edit(updater => updater.Remove(keys)); } - /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The key. - /// source. + /// + /// The intermediate cache. + /// The key of the item to remove. + /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3840,15 +4406,10 @@ public static void Remove(this IIntermediateCache source.Edit(updater => updater.Remove(key)); } - /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The keys. - /// source. + /// + /// The intermediate cache. + /// The keys to remove. + /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3859,15 +4420,14 @@ public static void Remove(this IIntermediateCache } /// - /// Removes the key which enables all observable list features of dynamic data. + /// Strips the key from a cache changeset, converting IChangeSet<TObject, TKey> to + /// IChangeSet<TObject> (list changeset). All indexed changes are dropped (sorting is not supported). /// - /// - /// All indexed changes are dropped i.e. sorting is not supported by this function. - /// - /// The type of object. - /// The type of key. - /// The source. - /// An observable which emits change sets. + /// The type of the object. + /// The type of the key. + /// The source changeset stream. + /// A list changeset stream without key information. + /// public static IObservable> RemoveKey(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3883,14 +4443,13 @@ public static IObservable> RemoveKey(this IOb } /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes a specific key from the cache. Equivalent to source.Edit(u => u.RemoveKey(key)). /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// source. + /// The source cache. + /// The key to remove. + /// is null. public static void RemoveKey(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3901,14 +4460,13 @@ public static void RemoveKey(this ISourceCache sou } /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. + /// Removes multiple keys from the cache in a single Edit call. Keys not present in the cache are ignored. /// /// The type of the object. /// The type of the key. - /// The source. - /// The keys. - /// source. + /// The source cache. + /// The keys to remove. + /// is null. public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3918,19 +4476,12 @@ public static void RemoveKeys(this ISourceCache so source.Edit(updater => updater.RemoveKeys(keys)); } - /// - /// Joins the left and right observable data sources, taking all right values and combining any matching left values. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -3947,18 +4498,48 @@ public static IObservable> RightJoin - /// Joins the left and right observable data sources, taking all right values and combining any matching left values. + /// Joins two changeset streams, producing a result for every right-side key. The left side is + /// because a matching left item may or may not exist. All right items + /// appear in the output regardless. Equivalent to SQL RIGHT OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). + /// An observable changeset keyed by . + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the matching left (or Optional.None) and the right value. + /// UpdateRe-invokes the selector with current left (if any) and the new right value. + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf matching right items exist, re-invokes the selector (left transitions from None to Some) and emits Updates. + /// UpdateIf matching right items exist, re-invokes the selector with the new left value. + /// RemoveIf matching right items exist, re-invokes the selector (left transitions from Some to None) and emits Updates. + /// RefreshIf joined results exist, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -3974,20 +4555,12 @@ public static IObservable> RightJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the two sources matching them using the specified key selector, , taking all right values and combining any matching left values. - /// This is the equivalent of SQL left join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4004,19 +4577,49 @@ public static IObservable> RightJoinMany - /// Groups the right data source and joins the two sources matching them using the specified key selector,, taking all right values and combining any matching left values. - /// This is the equivalent of SQL left join. + /// Groups right-side items by their mapped key, then right-joins each group to the left source. + /// A result is produced for every key that has at least one right item. The left value is + /// because a matching left item may or may not exist. + /// Equivalent to SQL RIGHT OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left data source. - /// The right data source. - /// Specify the foreign key on the right data source. - /// The result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If the group was previously empty, emits an Add with the current left (if any). Otherwise emits an Update. + /// UpdateUpdates the right group and re-invokes . + /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a non-empty right group exists, re-invokes the selector (left transitions from None to Some) and emits an Update. + /// UpdateIf a non-empty right group exists, re-invokes the selector with the new left value. + /// RemoveIf a non-empty right group exists, re-invokes the selector (left transitions from Some to None) and emits an Update. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4033,13 +4636,16 @@ public static IObservable> RightJoinMany - /// Defer the subscription until loaded and skip initial change set. + /// Skips the initial snapshot changeset that Connect() typically emits, then forwards all subsequent changesets. + /// Internally uses DeferUntilLoaded().Skip(1). /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits change sets. - /// source. + /// The source changeset stream. + /// An observable that skips the first changeset and forwards all others. + /// is null. + /// + /// public static IObservable> SkipInitial(this IObservable> source) where TObject : notnull where TKey : notnull @@ -4050,13 +4656,11 @@ public static IObservable> SkipInitial( } /// - /// Sorts using the specified comparer. - /// Returns the underlying ChangeSet as per the system conventions. - /// The resulting change set also exposes a sorted key value collection of the underlying cached data. + /// Obsolete: use SortAndBind instead. Sorts using the specified comparer. /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer. /// Sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). @@ -4078,11 +4682,11 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable. /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer observable. /// The sort optimisations. /// The reset threshold. @@ -4099,11 +4703,11 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable with a manual re-sort signal. /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer observable. /// Signal to instruct the algorithm to re-sort the entire data set. /// The sort optimisations. @@ -4121,11 +4725,11 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a static comparer with a manual re-sort signal. /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The comparer to sort on. /// Signal to instruct the algorithm to re-sort the entire data set. /// The sort optimisations. @@ -4143,16 +4747,18 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence by selected property. + /// Sorts the changeset stream by the value returned from . Creates a comparer internally + /// and delegates to . + /// Since Sort is obsolete, prefer SortAndBind for new code. /// /// The type of the object. /// The type of the key. - /// The source. - /// The expression. - /// The sort order. Defaults to ascending. - /// The sort optimisations. - /// The reset threshold. - /// An observable which emits change sets. + /// The source changeset stream. + /// Expression that selects a comparable value from each item. + /// The sort direction. Defaults to ascending. + /// Sort optimization flags. + /// The number of updates before the entire list is re-sorted (rather than inline sort). + /// An observable that emits sorted changesets. public static IObservable> SortBy( this IObservable> source, Func expression, @@ -4176,91 +4782,76 @@ public static IObservable> SortBy } /// - /// Prepends an empty change set to the source. + /// Prepends an empty changeset to the source stream, ensuring subscribers always receive an immediate + /// (empty) notification on subscription. Uses Rx's StartWith. /// - /// The object of the change set. - /// The key of the change set. + /// The type of the object. + /// The type of the key. /// The source observable change set. - /// An observable which emits change sets. + /// An observable that emits an empty changeset first, then all source changesets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source observable change set. - /// An observable which emits sorted change sets. + /// + /// The source observable sorted change set. + /// An observable that emits an empty sorted changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(SortedChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source observable change set. - /// An observable which emits virtual change sets. + /// + /// The source observable virtual change set. + /// An observable that emits an empty virtual changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(VirtualChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source observable change set. - /// An observable which emits paged change sets. + /// + /// The source observable paged change set. + /// An observable that emits an empty paged changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(PagedChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. + /// + /// The type of the object. + /// The type of the key. /// The grouping key type. - /// The source observable change set. - /// An observable which emits group change sets. + /// The source observable group change set. + /// An observable that emits an empty group changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(GroupChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. + /// + /// The type of the object. + /// The type of the key. /// The grouping key type. - /// The source observable change set. - /// An observable which emits immutable group change sets. + /// The source observable immutable group change set. + /// An observable that emits an empty immutable group changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(ImmutableGroupChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// + /// /// The type of the item. - /// The source read only collection. - /// A read only collection. + /// The source read only collection observable. + /// An observable that emits an empty collection first, then all source collections. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); - /// - /// The equivalent of rx StartsWith operator, but wraps the item in a change where reason is ChangeReason.Add. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The item. - /// An observable which emits change sets. + /// + /// The source changeset stream. + /// The item to prepend. The key is extracted from . + /// Overload for items that implement . Delegates to the explicit key overload. public static IObservable> StartWithItem(this IObservable> source, TObject item) where TObject : IKey where TKey : notnull @@ -4271,14 +4862,15 @@ public static IObservable> StartWithItem - /// The equivalent of rx StartWith operator, but wraps the item in a change where reason is ChangeReason.Add. + /// Prepends a changeset containing a single Add for the given item and key to the source stream. + /// The Rx equivalent of StartWith, but wrapped as a DynamicData changeset. /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// The key. - /// An observable which emits change sets. + /// The source changeset stream. + /// The item to prepend. + /// The key for the item. + /// An observable that emits a single-item Add changeset first, then all source changesets. public static IObservable> StartWithItem(this IObservable> source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -4290,19 +4882,38 @@ public static IObservable> StartWithItem - /// Subscribes to each item when it is added to the stream and un-subscribes when it is removed. All items will be unsubscribed when the stream is disposed. + /// Creates an subscription per item via . + /// Subscriptions are created on Add/Update and disposed on Update/Remove. All active subscriptions + /// are disposed when the stream completes, errors, or the subscription is disposed. /// /// The type of the object. /// The type of the key. - /// The source. - /// The subscription function. - /// An observable which emits a change set. - /// source - /// or - /// subscriptionFactory. + /// The source changeset stream. + /// Factory that creates an for each item. Called on Add and Update (for the new value). + /// A stream that forwards all changesets from unchanged. /// - /// Subscribes to each item when it is added or updates and un-subscribes when it is removed. + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddCalls , stores the returned . + /// UpdateDisposes the previous subscription, then calls for the new value. + /// RemoveDisposes the subscription for the removed item. + /// RefreshPassed through. No subscription change. + /// + /// + /// + /// Internally implemented using + /// and , so disposal semantics match . + /// + /// + /// Use this to tie per-item side effects (event subscriptions, polling timers, child observable subscriptions) + /// to the lifecycle of items in the cache. + /// /// + /// or is null. + /// + /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -4313,20 +4924,10 @@ public static IObservable> SubscribeMany(source, subscriptionFactory).Run(); } - /// - /// Subscribes to each item when it is added to the stream and unsubscribes when it is removed. All items will be unsubscribed when the stream is disposed. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The subscription function. - /// An observable which emits a change set. - /// source - /// or - /// subscriptionFactory. - /// - /// Subscribes to each item when it is added or updates and unsubscribes when it is removed. - /// + /// + /// The source changeset stream. + /// Factory that creates an for each item. Receives the item and its key. + /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -4348,18 +4949,9 @@ public static IObservable> SuppressRefresh source.WhereReasonsAreNot(ChangeReason.Refresh); - /// - /// Transforms an observable sequence of observable caches into a single sequence - /// producing values only from the most recent observable sequence. - /// Each time a new inner observable sequence is received, unsubscribe from the - /// previous inner observable sequence and clear the existing result set. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// - /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. - /// + /// + /// An observable that emits instances. + /// Overload that accepts observable caches. Internally calls Connect() on each cache and delegates to the changeset overload. public static IObservable> Switch(this IObservable> sources) where TObject : notnull where TKey : notnull @@ -4370,17 +4962,26 @@ public static IObservable> Switch(this } /// - /// Transforms an observable sequence of observable changes sets into an observable sequence - /// producing values only from the most recent observable sequence. - /// Each time a new inner observable sequence is received, unsubscribe from the - /// previous inner observable sequence and clear the existing result set. + /// Subscribes to the latest inner changeset stream, unsubscribing from the previous one on each switch. + /// When switching, the old source's items are removed and the new source's items are added. /// /// The type of the object. /// The type of the key. - /// The source. - /// - /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. - /// + /// An observable that emits inner changeset streams. + /// A changeset stream reflecting the items from the most recently emitted inner source. + /// + /// + /// EventBehavior + /// AddForwarded from the active inner source. + /// UpdateForwarded from the active inner source. + /// RemoveForwarded from the active inner source. + /// RefreshForwarded from the active inner source. + /// OnErrorAn error from any inner source or the outer source terminates the stream. + /// OnCompletedCompletes when the outer source and the current inner source have both completed. + /// + /// On switch: Remove is emitted for all items from the previous source, then Add for all items from the new source. + /// Worth noting: Each switch clears the entire downstream cache before populating from the new source. Subscribers see a full remove-then-add reset on every switch. + /// public static IObservable> Switch(this IObservable>> sources) where TObject : notnull where TKey : notnull @@ -4395,27 +4996,26 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull where TKey : notnull => source.QueryWhenChanged(query => new ReadOnlyCollectionLight(query.Items)); /// - /// Converts the observable to an observable change set. - /// Change set observes observable change events. + /// Bridges a standard Rx observable of individual items into a DynamicData changeset stream. + /// Each emission becomes an Add (or Update if the key already exists). + /// Supports optional per-item expiration and size limiting. /// /// The type of the object. /// The type of the key. - /// The source. - /// The key selector. - /// Specify on a per object level the maximum time before an object expires from a cache. - /// Remove the oldest items when the size has reached this limit. - /// The scheduler (only used for time expiry). - /// An observable which will emit changes. - /// source - /// or - /// keySelector. + /// The source observable of individual items. + /// Selects the unique key for each item. + /// Optional: per-item expiration time. Return null for no expiration. + /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// Optional scheduler for expiration timing. + /// An observable changeset stream. + /// or is null. public static IObservable> ToObservableChangeSet( this IObservable source, Func keySelector, @@ -4437,20 +5037,19 @@ public static IObservable> ToObservableChangeSet - /// Converts the observable to an observable change set. - /// Change set observes observable change events. + /// Bridges a standard Rx observable of item batches into a DynamicData changeset stream. + /// Each batch is processed with AddOrUpdate, producing Add or Update changes per item. + /// Supports optional per-item expiration and size limiting. /// /// The type of the object. /// The type of the key. - /// The source. - /// The key selector. - /// Specify on a per object level the maximum time before an object expires from a cache. - /// Remove the oldest items when the size has reached this limit. - /// The scheduler (only used for time expiry). - /// An observable change set. - /// source - /// or - /// keySelector. + /// The source observable of item batches. + /// Selects the unique key for each item. + /// Optional: per-item expiration time. Return null for no expiration. + /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// Optional scheduler for expiration timing. + /// An observable changeset stream. + /// or is null. public static IObservable> ToObservableChangeSet( this IObservable> source, Func keySelector, @@ -4472,15 +5071,34 @@ public static IObservable> ToObservableChangeSet - /// Converts an observable change set into an observable optional that emits the value for the given key. + /// Watches a single key in the source changeset stream, emitting Optional.Some(value) when the key + /// is present and Optional.None when it is removed. Duplicate values are suppressed via . /// /// The type of the object. /// The type of the key. - /// The source. - /// The key value. - /// Optional instance used to determine if an object value has changed. - /// An observable optional. - /// source is null. + /// The source changeset stream. + /// The key to watch. + /// Optional comparer to suppress duplicate emissions. Uses default equality if null. + /// An observable of Optional<TObject> that reflects the presence or absence of the specified key. + /// + /// + /// Unlike , this emits None on removal + /// (rather than the removed value), making it possible to distinguish "key is absent" from "key has a value". + /// + /// + /// EventBehavior + /// AddEmits Optional.Some(value) if the key was not previously tracked. + /// UpdateEmits Optional.Some(newValue) if the new value differs from the previous per . Otherwise suppressed. + /// RemoveEmits Optional.None. + /// RefreshEmits Optional.Some(value) if the value differs from the last emission per . Otherwise suppressed. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No emission occurs if the key is not present at subscription time. To get an initial None when the key is absent, use the overload with initialOptionalWhenMissing: true. + /// + /// is null. + /// + /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -4495,12 +5113,15 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The key value. /// Indicates if an initial Optional None should be emitted if the value doesn't exist. /// Optional instance used to determine if an object value has changed. /// An observable optional. /// source is null. + /// + /// Worth noting: Uses lock-based coordination. If the key exists synchronously on Connect(), the initial None may or may not be emitted depending on timing. + /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, bool initialOptionalWhenMissing, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -4525,7 +5146,7 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// The source. + /// The source changeset stream. /// The sort function. /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. @@ -4539,7 +5160,7 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) @@ -4552,21 +5173,8 @@ public static IObservable> ToSortedCollection(items); }); - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4578,21 +5186,8 @@ public static IObservable> Transform transformFactory(current), transformOnRefresh); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4604,21 +5199,8 @@ public static IObservable> Transform transformFactory(current, key), transformOnRefresh); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4630,21 +5212,8 @@ public static IObservable> Transform(source, transformFactory, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts an optional forceTransform predicate filtering by source item only (without the key). The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4656,21 +5225,8 @@ public static IObservable> Transform transformFactory(current), forceTransform?.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts an optional forceTransform predicate filtering by source item and key. The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4683,20 +5239,43 @@ public static IObservable> Transform - /// Projects each update item to a new form using the specified transform function. + /// Projects each item in the changeset to a new form using a synchronous transform factory. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Transform maintains a 1:1 mapping between source and destination items, keyed identically. The factory + /// is called once per Add and once per Update. Removes are forwarded without calling the factory. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls factory, emits Add. + /// UpdateCalls factory (receives current item, previous item, key), emits Update with Previous preserved. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshForwarded as Refresh without re-transforming. To re-transform on Refresh, use the parameter or the transformOnRefresh overloads. + /// + /// Worth noting: By default, Refresh does NOT re-invoke the transform factory (it is just forwarded). Set transformOnRefresh: true to re-transform on Refresh. + /// + /// When emits a predicate, every cached item is tested against it. + /// Matching items are re-transformed and emitted as Updates. + /// + /// + /// Factory exceptions propagate as , terminating the stream. + /// Use + /// to catch factory errors without killing the stream. + /// + /// + /// + /// + /// + /// or is null. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4712,41 +5291,15 @@ public static IObservable> Transform(source, transformFactory).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for all items. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.Transform((cur, _, _) => transformFactory(cur), forceTransform.ForForced()); - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -4759,21 +5312,8 @@ public static IObservable> Transform transformFactory(cur, key), forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -4786,21 +5326,8 @@ public static IObservable> Transform()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a simpler factory that receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4813,21 +5340,8 @@ public static IObservable> TransformAsync transformFactory(current), forceTransform); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4841,20 +5355,38 @@ public static IObservable> TransformAsync - /// Projects each update item to a new form using the specified transform function. + /// Async version of . + /// Projects each item using an async factory that returns . /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// An async function that produces a from the current source item, the previous source item (if any), and the key. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Transforms within a single changeset batch execute concurrently. The entire batch must complete + /// before the resulting changeset is emitted. Use the overloads + /// to control maximum concurrency and Refresh handling. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddAwaits factory, emits Add. + /// UpdateAwaits factory (receives current, previous, key), emits Update. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshForwarded as Refresh by default. Use to re-transform. + /// + /// Worth noting: Transforms are batched per changeset (all tasks must complete before the next changeset is processed). Completion waits for in-flight transforms. Remove does NOT cancel in-flight transforms for the removed key. + /// + /// Factory exceptions propagate as . Use + /// + /// to catch factory errors without terminating the stream. + /// + /// + /// or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4867,21 +5399,8 @@ public static IObservable> TransformAsync(source, transformFactory, null, forceTransform).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4894,21 +5413,8 @@ public static IObservable> TransformAsync transformFactory(current), options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4921,21 +5427,8 @@ public static IObservable> TransformAsync transformFactory(current, key), options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4949,26 +5442,31 @@ public static IObservable> TransformAsync - /// Projects each update item to a new form using the specified transform function, with optimizations for stateless/deterministic transformation of immutable items. + /// Optimized transform for immutable items with deterministic (pure) transform functions. + /// Refresh changes are dropped entirely since immutable items cannot change in place. /// - /// The type of collection items produced by the transformation. - /// The type of collection items to be transformed. - /// The type of the key values of each collection item. - /// The source stream of collection items to be transformed. - /// The transformation to be applied to each item. - /// A stream of collection changesets where upstream collection items are transformed by the given factory function. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. + /// An observable changeset of transformed items. /// - /// The goal of this operator is to optimize a common use-case of reactive programming, where data values flowing through a stream are immutable, and state changes are distributed by publishing new immutable items as replacements, instead of mutating the items directly. - /// In addition to assuming that all collection items are immutable, this operator also assumes that the given transformation function is deterministic, such that the result it returns will always be equivalent each time a specific input is passed to it. In other words, the transformation itself also contains no mutable state. - /// Under these assumptions, this operator can bypass the need to keep track of every collection item that passes through it, which the normal operator must do, in order to re-evaluate transformations during a refresh operation. - /// Consider using this operator when the following are true: - /// - /// Your collection items are immutable, and changes are published by replacing entire items - /// Your transformation logic does not change over the lifetime of the stream, only the items do - /// Your transformation function runs quickly, and does not heavily allocate memory + /// + /// Because the transform is assumed to be stateless and deterministic, this operator does not track + /// previously transformed items. This reduces memory overhead compared to . + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls factory, emits Add. + /// UpdateCalls factory, emits Update. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshDROPPED. Immutable items do not change, so Refresh is meaningless. /// - /// Note that, because transformation is purely deterministic, Refresh operations are transparently ignored by this operator. + /// Use this when items are immutable, the factory is pure, and the factory is cheap. If any of these conditions are false, use instead. /// + /// or is null. public static IObservable> TransformImmutable( this IObservable> source, Func transformFactory) @@ -4986,67 +5484,55 @@ public static IObservable> TransformImmutable - /// Equivalent to a select many transform. To work, the key must individually identify each child. + /// Flattens each source item into zero or more destination items (1:N), producing a single flat changeset. + /// Each child item must have a globally unique key across all parents. /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Will select a enumerable of values. - /// The key selector which must be unique across all. + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. + /// Extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. + /// An observable changeset of flattened child items. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls , emits Add for each child. + /// UpdateDiffs old children vs new children: emits Remove for removed children, Add for new children, Update for children with matching keys. + /// RemoveEmits Remove for all children of the removed parent. + /// RefreshPropagated as Refresh to all children (no re-expansion). + /// + /// Worth noting: If two source items produce children with the same key, last-in-wins. Refresh does NOT re-expand children (only Update does). + /// If two parents produce children with the same key, last-in-wins. Use the async variant with a to control conflict resolution. + /// + /// , , or is null. + /// public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable collection, and subsequently observe observable collection changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Will select a enumerable of values. - /// The key selector which must be unique across all. + /// + /// This overload accepts an selector. Changes to the child collection (adds, removes, replacements) are automatically observed and reflected downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable collection, and subsequently observe observable collection changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Will select a enumerable of values. - /// The key selector which must be unique across all. + /// + /// This overload accepts a selector. Changes to the child collection are automatically observed and reflected downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable cache, and subsequently observe observable cache changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Will select an observable cache of values. - /// The key selector which must be unique across all. + /// + /// This overload accepts an selector. The child cache is live: subsequent changes to it are automatically propagated downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull @@ -5054,19 +5540,31 @@ public static IObservable> TransformMa where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// Async version of . + /// Flattens each source item into zero or more destination items using an async factory. /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source. - /// Async function to transform a and into an of . - /// The key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// An async function that expands a parent item (and its key) into an of children. + /// Extracts a unique key from each child item. + /// Optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. + /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. + /// An observable changeset of flattened child items. + /// + /// + /// Because each parent's expansion is async, child collections may arrive via separate changesets + /// (unlike the synchronous TransformMany which batches all children into one changeset). + /// + /// + /// Factory exceptions propagate as . Use + /// + /// to catch errors without killing the stream. + /// + /// + /// or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5080,20 +5578,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source. - /// Async function to transform a into an of . - /// The key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload takes a factory that receives only the source item (without the key). [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5102,21 +5588,8 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a and into an of . - /// The key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5131,21 +5604,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a into an of . - /// The key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5155,19 +5615,8 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a and into an of . - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live: its changes propagate downstream. No keySelector is needed since the cache already has keys. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5181,19 +5630,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a and into an of . - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5203,20 +5641,23 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), equalityComparer, comparer); /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source. - /// Async function to transform a and into an of . - /// The key selector which must be unique across all. - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// Async version of + /// with error handling. Factory exceptions are caught and routed to instead of + /// terminating the stream. + /// + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// An async function that expands a parent item (and its key) into an of children. + /// Extracts a unique key from each child item. + /// Called when throws. The faulting item is skipped and the stream continues. + /// Optional comparer to determine if two child items with the same key are equal. + /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. + /// An observable changeset of flattened child items. + /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. + /// , , or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5231,21 +5672,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source. - /// Async function to transform a into an of . - /// The key selector which must be unique across all. - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload takes a factory that receives only the source item (without the key). [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5254,22 +5682,8 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a and into an of . - /// The key selector which must be unique across all. - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5285,22 +5699,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a into an of . - /// The key selector which must be unique across all. - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5310,20 +5710,8 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a and into an of . - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5338,20 +5726,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source. - /// Async function to transform a into an of . - /// Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5361,19 +5737,32 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), errorHandler, equalityComparer, comparer); /// - /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. + /// Projects each item into a per-item observable. The latest value emitted by each item's observable + /// becomes the transformed value in the output changeset. /// - /// The type of the source changeset. + /// The type of the source items. /// The type of the key. - /// The type of the destination changeset. + /// The type of the transformed items. /// The source changeset observable. - /// Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. - /// - /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. - /// - /// source - /// or - /// transformFactory. + /// A function that, given a source item and its key, returns an whose emissions become the transformed values. + /// An observable changeset where each key's value is the latest emission from its per-item observable. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddSubscribes to the per-item observable. First emission: Add downstream. Subsequent emissions: Update. + /// UpdateDisposes old subscription, subscribes to new item's observable. + /// RemoveDisposes subscription, emits Remove. + /// RefreshForwarded if item is currently downstream. + /// + /// Worth noting: Items do not appear downstream until the per-item observable emits its first value. Per-item observable errors terminate the entire stream. + /// + /// An error from any per-item observable terminates the entire stream. + /// The per-item observable's selector runs under an internal lock, so it must not synchronously + /// access other DynamicData caches (deadlock risk in cross-cache pipelines). + /// + /// + /// or is null. public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5385,18 +5774,8 @@ public static IObservable> TransformOnObservable< return new TransformOnObservable(source, transformFactory).Run(); } - /// - /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. - /// - /// The type of the source changeset. - /// The type of the key. - /// The type of the destination changeset. - /// The source changeset observable. - /// Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. - /// - /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. - /// - /// source or transformFactory. + /// + /// This overload takes a factory that receives only the source item (without the key). public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5407,23 +5786,8 @@ public static IObservable> TransformOnObservable< return source.TransformOnObservable((obj, _) => transformFactory(obj)); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a simpler factory that receives only the current item, and a forceTransform predicate filtering by source item only. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5436,23 +5800,8 @@ public static IObservable> TransformSafe transformFactory(current), errorHandler, forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a factory that receives the current item and key. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5466,22 +5815,26 @@ public static IObservable> TransformSafe - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. + /// Projects each item using a synchronous factory, catching factory exceptions via a mandatory error handler + /// instead of terminating the stream. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Behaves identically to + /// except that factory exceptions are routed to instead of propagating as . + /// Source-level errors (i.e. the source observable itself erroring) still propagate normally. + /// + /// Worth noting: Factory exceptions are caught per-item; the faulting item is skipped and reported to the error handler while the stream continues. Source-level errors still terminate the stream. + /// + /// , , or is null. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5498,45 +5851,15 @@ public static IObservable> TransformSafe(source, transformFactory, errorHandler).Run(); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for all items. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. The factory receives only the current item. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.TransformSafe((cur, _, _) => transformFactory(cur), errorHandler, forceTransform.ForForced()); - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. The factory receives the current item and key. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5549,23 +5872,8 @@ public static IObservable> TransformSafe transformFactory(cur, key), errorHandler, forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Provides the option to safely handle errors without killing the stream. - /// Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5578,22 +5886,8 @@ public static IObservable> TransformSafe()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5607,22 +5901,8 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, forceTransform); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5637,21 +5917,19 @@ public static IObservable> TransformSafeAsync - /// Projects each update item to a new form using the specified transform function. + /// Async version of . + /// Projects each item using an async factory, catching factory exceptions via a mandatory error handler. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// An async function that produces a . + /// Called when throws or faults. The item is skipped and the stream continues. + /// Optional observable to force re-transformation of matching items. + /// An observable changeset of transformed items. + /// Combines the async execution model of with the error-safe behavior of . + /// , , or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5665,22 +5943,8 @@ public static IObservable> TransformSafeAsync(source, transformFactory, errorHandler, forceTransform).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5694,22 +5958,8 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5723,22 +5973,8 @@ public static IObservable> TransformSafeAsync transformFactory(current, key), errorHandler, options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// The error handler. - /// Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5753,14 +5989,27 @@ public static IObservable> TransformSafeAsync - /// Transforms the object to a fully recursive tree, create a hierarchy based on the pivot function. + /// Builds a hierarchical tree from a flat changeset using a parent key selector. + /// Each item becomes a with Parent, Children, Depth, and IsRoot properties. /// - /// The type of the object. + /// The type of the source items. Must be a reference type. /// The type of the key. - /// The source. - /// The pivot on. - /// Observable to change the underlying predicate. - /// An observable which will emit change sets. + /// The source changeset of flat items. + /// A function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. + /// Optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. + /// An observable changeset of items representing the tree. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCreates node, attaches to parent (or root if parent not found), emits Add. + /// UpdateUpdates node. If returns a different parent key, the node is re-parented. + /// RemoveRemoves node. Orphaned children become root nodes. + /// RefreshRe-evaluates parent key. May re-parent the node if the parent changed. + /// + /// Circular references are NOT detected. If item A is the parent of B and B is the parent of A, behavior is undefined. + /// + /// or is null. public static IObservable, TKey>> TransformToTree(this IObservable> source, Func pivotOn, IObservable, bool>>? predicateChanged = null) where TObject : class where TKey : notnull @@ -5771,21 +6020,8 @@ public static IObservable, TKey>> TransformToTree return new TreeBuilder(source, pivotOn, predicateChanged).Run(); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload defaults to transformOnRefresh: false and does not provide an error handler (factory exceptions propagate as OnError). public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction) where TDestination : class where TSource : notnull @@ -5798,22 +6034,8 @@ public static IObservable> TransformWithInlineUpd return source.TransformWithInlineUpdate(transformFactory, updateAction, false); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload does not provide an error handler (factory exceptions propagate as OnError). The transformOnRefresh parameter controls Refresh behavior. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -5826,22 +6048,8 @@ public static IObservable> TransformWithInlineUpd return new TransformWithInlineUpdate(source, transformFactory, updateAction, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// The error handler. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload defaults to transformOnRefresh: false but includes an error handler for factory/update action exceptions. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler) where TDestination : class where TSource : notnull @@ -5856,22 +6064,33 @@ public static IObservable> TransformWithInlineUpd } /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. + /// Projects each item using a transform factory for Add, and mutates the existing transformed + /// item in place (via an update action) for Update, preserving the original object reference. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source. - /// The transform factory. - /// Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// The error handler. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. Must be a reference type since items are mutated in place. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// Called on Add (and optionally Refresh) to create a new . + /// Called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. + /// Called when or throws. The faulting item is skipped. + /// When true, Refresh changes call on the existing item. + /// An observable changeset of transformed items. + /// + /// + /// This is useful when the destination type is a ViewModel that should maintain its identity across updates. + /// Instead of replacing the entire ViewModel, the update action patches the existing instance. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls , emits Add. + /// UpdateCalls on the EXISTING transformed item (same reference), emits Update. + /// RemoveEmits Remove. + /// RefreshIf is true, calls . Otherwise forwarded as Refresh. + /// + /// + /// , , , or is null. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -5890,7 +6109,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -5919,23 +6138,30 @@ static IEnumerable> ReplaceMoves(IChangeSet } /// - /// - /// Produces a boolean observable indicating whether the latest resulting value from all of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever. - /// - /// - /// i) The cache changes - /// or ii) The inner observable changes. - /// + /// Emits true when all items in the cache satisfy a condition based on their per-item observable, + /// and false otherwise. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. - /// The type of the value. - /// The source. - /// Selector which returns the target observable. - /// The equality condition. - /// An observable which boolean values indicating if true. - /// source. + /// The type of the value emitted by each per-item observable. + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each per-item observable's latest value. + /// An observable of bool that emits whenever the all-items condition changes. + /// , , or is null. + /// + /// + /// EventBehavior + /// AddA new per-item subscription is created. The aggregate condition is recalculated. + /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. + /// RemovePer-item subscription disposed. Condition recalculated over remaining items. + /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. + /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. + /// OnCompletedCompletes when the source and all per-item observables have completed. + /// + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache is vacuously true. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// + /// public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -5954,7 +6180,7 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// The source. + /// The source changeset stream. /// Selector which returns the target observable. /// The equality condition. /// An observable which boolean values indicating if true. @@ -5965,50 +6191,40 @@ public static IObservable TrueForAll(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.All(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever - /// i) The cache changes. - /// or ii) The inner observable changes. + /// Emits true when any item in the cache satisfies a condition based on its per-item observable, + /// and false when none do. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. - /// The type of the value. - /// The source. - /// The observable selector. - /// The equality condition. - /// An observable which boolean values indicating if true. - /// - /// source - /// or - /// observableSelector - /// or - /// equalityCondition. - /// + /// The type of the value emitted by each per-item observable. + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each item and its per-item observable's latest value. + /// An observable of bool that emits whenever the any-item condition changes. + /// , , or is null. + /// + /// + /// EventBehavior + /// AddA new per-item subscription is created. The aggregate condition is recalculated. + /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. + /// RemovePer-item subscription disposed. Condition recalculated over remaining items. + /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. + /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. + /// OnCompletedCompletes when the source and all per-item observables have completed. + /// + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache yields false. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// + /// public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); - /// - /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever - /// i) The cache changes. - /// or ii) The inner observable changes. - /// - /// The type of the object. - /// The type of the key. - /// The type of the value. - /// The source. - /// The observable selector. - /// The equality condition. - /// An observable which boolean values indicating if true. - /// - /// source - /// or - /// observableSelector - /// or - /// equalityCondition. - /// + /// + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each per-item observable's latest value (without the item). + /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -6022,24 +6238,36 @@ public static IObservable TrueForAny(this IObservab } /// - /// Updates the index for an object which implements IIndexAware. + /// Sets the Index property on each item (which must implement ) + /// to reflect its position in the sorted output. Operates on . /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable which emits the sorted change set. + /// The source sorted changeset stream. + /// An observable that emits the sorted changesets after updating item indices. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware where TKey : notnull => source.Do(changes => changes.SortedItems.Select((update, index) => new { update, index }).ForEach(u => u.update.Value.Index = u.index)); /// - /// Returns an observable of any updates which match the specified key, proceeded with the initial cache state. + /// Filters the source changeset stream to a single key, emitting each for that key. + /// Changes for all other keys are ignored. /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// An observable which emits the change. + /// The source changeset stream. + /// The key to observe. + /// An observable of for the specified key only. + /// + /// + /// Emits Add, Update, Remove, and Refresh changes as they occur for the target key. + /// No initial emission occurs if the key is not yet present in the cache. This operator does not + /// produce changesets; it produces individual change notifications. For Optional-based watching, + /// use . + /// + /// + /// + /// public static IObservable> Watch(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6050,14 +6278,33 @@ public static IObservable> Watch(this IObse } /// - /// Watches updates for a single value matching the specified key. + /// Filters the source changeset stream to a single key, emitting the current value each time it changes. + /// Even emits the value on removal (the removed item's value). /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// An observable which emits the object value. - /// source. + /// The source changeset stream. + /// The key to observe. + /// An observable of the item's value whenever it changes for the specified key. + /// + /// + /// Unlike , + /// this does not emit Optional.None on removal. It emits the removed item's value instead. + /// If you need to distinguish presence from absence, use ToObservableOptional. + /// + /// + /// EventBehavior + /// AddEmits the added item's value. + /// UpdateEmits the new value. + /// RemoveEmits the removed item's value (not None; use if you need removal detection). + /// RefreshEmits the current value. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No emission occurs if the key is not present at subscription time. Changes to other keys are ignored entirely. + /// + /// + /// public static IObservable WatchValue(this IObservableCache source, TKey key) where TObject : notnull where TKey : notnull @@ -6067,15 +6314,10 @@ public static IObservable WatchValue(this IObservableCac return source.Watch(key).Select(u => u.Current); } - /// - /// Watches updates for a single value matching the specified key. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The key. - /// An observable which emits the object value. - /// source. + /// + /// The source changeset stream. + /// The key to observe. + /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6086,13 +6328,34 @@ public static IObservable WatchValue(this IObservable - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits an item whenever any of its properties change via . + /// Subscribes to PropertyChanged on each cache item using MergeMany. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The source. - /// specify properties to Monitor, or omit to monitor all property changes. - /// An observable which emits the object which has had a property changed. + /// The source changeset stream. + /// Specific property names to monitor. If empty, all property changes trigger emissions. + /// An observable that emits the item itself each time a monitored property changes. + /// + /// + /// Subscriptions are managed per item: created on Add, replaced on Update, disposed on Remove. + /// Errors from individual property subscriptions are silently ignored. The output is not a changeset + /// stream; it is a plain IObservable<TObject?>. If the same item changes multiple properties + /// rapidly, each change emits the item separately (no deduplication). + /// + /// + /// EventBehavior + /// AddSubscribes to PropertyChanged on the new item. + /// UpdateDisposes the old item's subscription and subscribes to the new item. + /// RemoveDisposes the item's PropertyChanged subscription. + /// RefreshNo effect on subscriptions. + /// OnErrorErrors from individual property subscriptions are silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source changeset stream completes. + /// + /// + /// + /// + /// public static IObservable WhenAnyPropertyChanged(this IObservable> source, params string[] propertiesToMonitor) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6103,15 +6366,32 @@ public static IObservable WatchValue(this IObservable - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits a (item + property value) whenever the specified property + /// changes on any item in the cache. Subscribes via using MergeMany. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The type of the value. - /// The source. - /// The property accessor. - /// If true the resulting observable includes the initial value. - /// An observable which emits a property when it has changed. + /// The type of the monitored property. + /// The source changeset stream. + /// Expression selecting the property to monitor. + /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// An observable of containing both the item and its property value. + /// + /// + /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual + /// property subscriptions are silently ignored. The output is not a changeset stream. If you only need + /// the value (not the owning item), use instead. + /// + /// + /// EventBehavior + /// AddSubscribes to the specified property on the new item. If notifyOnInitialValue is true, the current value is emitted immediately. + /// UpdateDisposes the old item's property subscription and subscribes to the new item. + /// RemoveDisposes the item's property subscription. No further emissions for this item. + /// RefreshNo effect on subscriptions. The existing property subscription continues. + /// OnErrorPer-item property subscription errors are silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source changeset stream completes. + /// + /// public static IObservable> WhenPropertyChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6123,15 +6403,35 @@ public static IObservable> WhenPropertyChanged - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits the property value whenever the specified property changes on any item in the cache. + /// Like but emits only the value, discarding the owning item. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The type of the value. - /// The source. - /// The property accessor. - /// If true the resulting observable includes the initial value. - /// An observable which emits a value when it has changed. + /// The type of the monitored property. + /// The source changeset stream. + /// Expression selecting the property to monitor. + /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// An observable of property values. The owning item is not included; use if you need it. + /// + /// + /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual + /// property subscriptions are silently ignored. If you need to correlate a value back to its source item, + /// use which returns a pair. + /// + /// + /// EventBehavior + /// AddSubscribes to the specified property. If notifyOnInitialValue is true, the current value is emitted immediately. + /// UpdateDisposes the old subscription, subscribes to the new item's property. + /// RemoveDisposes the property subscription. + /// RefreshNo effect on subscriptions. + /// OnErrorPer-item errors silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source completes. + /// + /// + /// + /// + /// public static IObservable WhenValueChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6147,11 +6447,14 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The reasons. /// An observable which emits a change set with items matching the reasons. /// reasons. /// Must select at least on reason. + /// + /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. + /// public static IObservable> WhereReasonsAre(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6174,11 +6477,14 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// The source. + /// The source changeset stream. /// The reasons. /// An observable which emits a change set with items not matching the reasons. /// reasons. /// Must select at least on reason. + /// + /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. + /// public static IObservable> WhereReasonsAreNot(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6196,19 +6502,34 @@ public static IObservable> WhereReasonsAreNot - /// Apply a logical Xor operator between the collections. - /// Items which are only in one of the sources are included in the result. + /// Combines multiple changeset streams using logical XOR (symmetric difference). + /// An item appears downstream only if it exists in exactly one source. /// /// The type of the object. /// The type of the key. - /// The source. - /// The others. - /// An observable which emits a change set. - /// - /// source - /// or - /// others. - /// + /// The first source changeset stream. + /// Additional changeset streams to combine with. + /// A changeset stream containing items present in exactly one source. + /// + /// + /// Items are tracked via reference counting. An item appears downstream only when exactly one + /// source holds it. Adding the same key from a second source removes it from the result; + /// removing from that second source restores it. + /// + /// + /// EventBehavior + /// AddIf the key is now held by exactly one source, an Add is emitted. If adding causes the count to reach 2+, a Remove is emitted (the item is no longer exclusive). + /// UpdateIf the item is currently downstream (count is 1), an Update is emitted. + /// RemoveReference count decremented. If the count drops to exactly 1, an Add is emitted (the item is now exclusive to one source). If it drops to 0, a Remove is emitted. + /// RefreshIf the item is downstream, a Refresh is forwarded. + /// OnErrorAn error from any source terminates the combined output. + /// OnCompletedThe output completes when all sources have completed. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> Xor(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -6223,19 +6544,9 @@ public static IObservable> Xor(this IOb return source.Combine(CombineOperator.Xor, others); } - /// - /// Apply a logical Xor operator between the collections. - /// Items which are only in one of the sources are included in the result. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable which emits a change set. - /// - /// source - /// or - /// others. - /// + /// + /// A fixed collection of changeset streams to combine. + /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Xor(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -6251,7 +6562,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull @@ -6268,7 +6579,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull @@ -6285,7 +6596,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull From 09b0022decba7473c48949fa664fb3886f2926a9 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Mon, 13 Apr 2026 18:45:16 -0700 Subject: [PATCH 02/23] docs: flesh out MergeChangeSets and MergeManyChangeSets documentation MergeManyChangeSets now has separate parent-side and child-side event tables, mirroring the join operator documentation style. Describes parent Add/Update/ Remove effects on child subscriptions, and child Add/Update/Remove/Refresh effects on downstream with conflict resolution details. MergeChangeSets adds overload family guide explaining the three axes: source type (dynamic/pair/static), conflict resolution (none/comparer/equality/both), and completion behavior (completable flag). --- src/DynamicData/Cache/ObservableCacheEx.cs | 86 ++++++++++++++++------ 1 file changed, 62 insertions(+), 24 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index ad6a7ac30..3a1011e12 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -2892,10 +2892,21 @@ public static IObservable MergeMany(t /// A unified changeset stream containing changes from all active source streams. /// /// - /// Each inner changeset stream is independently tracked. When multiple sources provide the same key, + /// Each inner changeset stream is independently tracked in its own cache. When multiple sources provide the same key, /// this overload uses first-in-wins semantics: the value from whichever source added the key first is /// the one published downstream. To control which value wins for duplicate keys, use an overload that /// accepts an , which selects the lowest-ordered value across all sources. + /// An can be provided separately to suppress no-op updates when + /// the new value equals the currently published value for a key. + /// + /// + /// Overload families: MergeChangeSets has 16 overloads organized along three axes: + /// (1) Source type: dynamic (IObservable<IObservable<IChangeSet>>, sources arrive at runtime), + /// pair (source + other, exactly two streams), or static (IEnumerable, all sources known up front). + /// (2) Conflict resolution: none (first-in-wins), IComparer (lowest-ordered wins), + /// IEqualityComparer (suppresses duplicate updates), or both. + /// (3) Completion: static overloads accept a completable flag; when false, the output never completes + /// even after all sources finish (useful for "live" merge scenarios). /// /// /// EventBehavior @@ -2904,7 +2915,7 @@ public static IObservable MergeMany(t /// RemoveIf the removed value was the one published downstream, the operator scans all remaining sources for the same key. If another source still holds that key, an Update is emitted with the replacement value (selected by comparer if provided, otherwise the next available). If no other source holds the key, a Remove is emitted. /// RefreshIf the refreshed item matches the currently published value, the Refresh is forwarded. With a comparer, all sources are re-evaluated first; if a different value now wins, an Update is emitted instead of the Refresh. /// OnErrorAn error from any source (outer or inner) terminates the entire merged output. - /// OnCompletedThe output completes when the outer observable completes and all subscribed inner observables have also completed. + /// OnCompletedFor dynamic overloads, the output completes when the outer observable completes and all subscribed inner observables have also completed. For static overloads, completion depends on the completable parameter (default true). /// /// /// Worth noting: When a source removes a key that was published downstream, the fallback to another @@ -3354,38 +3365,65 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child cache changeset stream produced by - /// and merges all child changes into a single flattened output stream. - /// Child subscriptions follow the source item lifecycle: created on Add, replaced on Update (the old - /// subscription is disposed), and disposed on Remove (emitting Removes for all of that item's children). + /// For each item in the source cache, subscribes to a child changeset stream and merges all child + /// changes into a single flattened output stream. Child subscriptions track the parent item lifecycle: + /// created on Add, replaced on Update, disposed on Remove. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. + /// The type of items in the source (parent) cache. + /// The type of the key identifying parent items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. - /// A merged changeset stream containing items from all active child streams. + /// The source cache changeset stream whose items each produce a child changeset stream. + /// Factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. + /// Optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. + /// Optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. + /// A merged changeset stream containing all child items from all active parent subscriptions. /// /// - /// Unlike , - /// errors from child changeset streams propagate to the output (they are not silently swallowed). - /// An error from the source or any child terminates the merged output. + /// This is the changeset-aware counterpart to . + /// Where MergeMany produces a flat IObservable<T>, MergeManyChangeSets produces an IObservable<IChangeSet> + /// that tracks the full lifecycle of child items, including key conflict resolution across parents. + /// + /// + /// Parent-side change handling (source changeset events): + /// + /// + /// EventBehavior + /// AddCalls with the new parent item to obtain a child changeset stream, then subscribes. As the child stream emits changesets, those child items are merged into the output. The downstream observer sees Add changes for each new child item. + /// UpdateDisposes the previous parent's child subscription (removing all of its contributed child items from the output as Remove changes), then creates a new child subscription for the updated parent. The new child's items appear as Add changes. + /// RemoveDisposes the parent's child subscription. All child items contributed by that parent are emitted as Remove changes in the output. If another parent also provides a child with the same destination key, that parent's value is promoted as an Update (not an Add). + /// RefreshNo effect on the child subscription. The parent's child stream continues unchanged. + /// + /// + /// Child-side change handling (changes arriving from child changeset streams): /// /// /// EventBehavior - /// AddSubscribes to the child changeset stream for the new source item. All changes from the child are merged into the output. - /// UpdateDisposes the old child subscription, subscribes to a new child stream for the updated item. Items from the old child are removed from the output. - /// RemoveDisposes the child subscription. All items contributed by that child are emitted as Remove changes in the output. - /// RefreshNo effect on child subscriptions. - /// OnErrorErrors from child changeset streams propagate and terminate the output (unlike MergeMany which swallows child errors). - /// OnCompletedCompletes when the source completes and all active child streams have also completed. + /// AddIf the destination key is new, an Add is emitted. If another parent already contributed a child with the same key, the conflict is resolved by (lowest wins) or first-in-wins if no comparer. The losing value is tracked internally but not emitted. + /// UpdateIf this parent currently owns the destination key downstream, an Update is emitted. With a comparer, all parents are re-evaluated for that key; a different parent's value may win, producing an Update to that value instead. + /// RemoveIf this parent's value was the one published downstream for that destination key, the operator scans other parents for the same key. If found, an Update is emitted with the replacement. If not, a Remove is emitted. + /// RefreshIf the child item is the one currently published downstream, the Refresh is forwarded. With a comparer, all parents are re-evaluated first; if a different value now wins, an Update is emitted instead. /// - /// Worth noting: When multiple children produce items with the same destination key, the determines which value wins. Without a comparer, first-in-wins. The suppresses no-op updates when the new value equals the current one. + /// + /// Error and completion: + /// + /// + /// EventBehavior + /// OnErrorAn error from the source (parent) stream or from any child changeset stream terminates the entire output. Unlike , child errors are NOT swallowed. + /// OnCompletedThe output completes when the source (parent) stream completes and all active child changeset streams have also completed. + /// + /// + /// Worth noting: When multiple parents contribute children with the same destination key, only one value is published + /// downstream at a time. The controls which value wins; without it, the first parent to add the key + /// retains priority. Removing a parent that owned a contested key causes the next-best value (per comparer or next available) + /// to surface as an Update, not an Add. The independently controls whether a child + /// Update for an already-published key is suppressed when the new value equals the old. + /// /// - /// or is null. + /// or is null. + /// + /// + /// public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull From 6a5bffca55846902f41aa64473c2610a8456d1a5 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Mon, 13 Apr 2026 19:05:01 -0700 Subject: [PATCH 03/23] docs: add two-table structure to *OnObservable operators FilterOnObservable, GroupOnObservable, and TransformOnObservable now each have two event tables: one for source changeset events (parent lifecycle) and one for per-item observable events (filter/group/transform emissions). All three explicitly call out that items are invisible downstream until their per-item observable emits at least one value. Per-item observable completion freezes the item in its current state; errors terminate the stream. --- src/DynamicData/Cache/ObservableCacheEx.cs | 110 +++++++++++++++++---- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 3a1011e12..761e5c2d3 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -1786,15 +1786,34 @@ public static IObservable> FilterImmutableOptional scheduler used for buffering. /// An observable changeset containing only items whose per-item observable most recently emitted true. /// + /// + /// Source changeset handling (parent events): + /// /// /// EventBehavior - /// AddSubscribes to the per-item observable. When it first emits true, an Add is emitted downstream. Subsequent false/true emissions toggle inclusion (emitting Remove/Add). - /// UpdateDisposes the old item's subscription and subscribes to the new item's observable. Inclusion state is re-evaluated. - /// RemoveDisposes the item's subscription. If the item was included downstream, a Remove is emitted. - /// RefreshForwarded as Refresh if the item is currently included downstream. - /// OnErrorForwarded. Also triggered if any per-item observable errors. - /// OnCompletedForwarded to the downstream observer. + /// AddSubscribes to the per-item observable. The item is not included downstream until the observable emits its first true. + /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. Inclusion state is reset; the new observable must emit before the item reappears. + /// RemoveDisposes the item's observable subscription. If the item was included downstream, a Remove is emitted. + /// RefreshForwarded as Refresh if the item is currently included downstream. Otherwise dropped. + /// + /// + /// Per-item observable handling (filter observable events): + /// + /// + /// EmissionBehavior + /// First trueThe item is included: an Add is emitted downstream. + /// false (was included)The item is excluded: a Remove is emitted downstream. + /// true (was excluded)The item is re-included: an Add is emitted downstream. + /// true (was included)No effect (already included). + /// false (was excluded)No effect (already excluded). + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains in its current inclusion state. No further toggling is possible for this item. /// + /// + /// Worth noting: Items are invisible downstream until their per-item observable emits at least one true. + /// If an item's observable never emits, the item never appears. The parameter batches + /// rapid inclusion changes from per-item observables into a single re-evaluation, reducing changeset chatter. + /// /// /// or is null. /// @@ -2214,17 +2233,52 @@ public static IObservable> Group - /// Groups the source by the latest value from their observable created by the given factory. + /// Groups items where each item's group key is determined by a per-item observable. + /// The observable is created by for each item. /// /// The type of the object. /// The type of the key. /// The type of the group key. /// The source changeset stream. - /// The group selector key. - /// An observable which will emit group change sets. + /// Factory that creates a group key observable for each item and its key. + /// An observable that emits group changesets. Each group is a live sub-cache of its members. /// - /// Worth noting: Items do not appear in any group until their per-item observable emits the first group key. Per-item observable errors terminate the entire stream. + /// + /// Unlike which evaluates + /// the group key synchronously, this operator defers group assignment until the per-item observable emits. + /// + /// + /// Source changeset handling (parent events): + /// + /// + /// EventBehavior + /// AddSubscribes to the per-item group key observable. The item is not placed in any group until the observable emits its first group key. + /// UpdateDisposes the old item's group key subscription and subscribes to the new item's observable. The item is removed from its current group until the new observable emits. + /// RemoveDisposes the item's group key subscription. The item is removed from its current group. Empty groups are removed. + /// RefreshNo effect on subscriptions. The item remains in its current group. + /// + /// + /// Per-item observable handling (group key observable events): + /// + /// + /// EmissionBehavior + /// First valueThe item is placed into the group matching the emitted key. An Add appears in that group's sub-cache. If the group is new, the group itself is added to the output. + /// New value (different key)The item moves: Remove from the old group, Add to the new group. If the old group becomes empty, it is removed from the output. + /// Same value (unchanged key)No effect (filtered by DistinctUntilChanged). + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains in its current group. No further group key changes are possible for this item. + /// + /// + /// Worth noting: Items are invisible (not in any group) until their per-item observable emits at least one + /// group key. If an item's observable never emits, the item never appears in any group. Per-item observable errors + /// terminate the entire stream. The output completes when the source completes and all per-item observables have + /// also completed. + /// /// + /// + /// + /// + /// public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull where TKey : notnull @@ -5785,22 +5839,38 @@ public static IObservable> TransformMa /// A function that, given a source item and its key, returns an whose emissions become the transformed values. /// An observable changeset where each key's value is the latest emission from its per-item observable. /// - /// Change reason handling: + /// + /// Source changeset handling (parent events): + /// /// - /// Input reasonOutput behavior - /// AddSubscribes to the per-item observable. First emission: Add downstream. Subsequent emissions: Update. - /// UpdateDisposes old subscription, subscribes to new item's observable. - /// RemoveDisposes subscription, emits Remove. - /// RefreshForwarded if item is currently downstream. + /// EventBehavior + /// AddCalls and subscribes to the returned observable. The item is not visible downstream until the observable emits its first value. + /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. The item disappears from downstream until the new observable emits. + /// RemoveDisposes the item's observable subscription. If the item was visible downstream, a Remove is emitted. + /// RefreshForwarded as Refresh if the item is currently visible downstream. Otherwise dropped. /// - /// Worth noting: Items do not appear downstream until the per-item observable emits its first value. Per-item observable errors terminate the entire stream. /// - /// An error from any per-item observable terminates the entire stream. - /// The per-item observable's selector runs under an internal lock, so it must not synchronously - /// access other DynamicData caches (deadlock risk in cross-cache pipelines). + /// Per-item observable handling (transform observable events): + /// + /// + /// EmissionBehavior + /// First valueThe transformed item appears downstream as an Add. + /// Subsequent valuesEach new value replaces the previous one: an Update is emitted downstream. + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains at its last emitted value. No further updates are possible for this item. + /// + /// + /// Worth noting: Items are invisible downstream until their per-item observable emits at least one value. + /// If an item's observable never emits, that item never appears in the output. The transform factory's selector + /// runs under an internal lock, so it must not synchronously access other DynamicData caches (deadlock risk in + /// cross-cache pipelines). The output completes when the source completes and all per-item observables have + /// also completed. /// /// /// or is null. + /// + /// + /// public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull From 9572e2b8dc1fffd6ee018290dc120117cd9071a2 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 07:22:58 -0700 Subject: [PATCH 04/23] docs: link types with see/cref instead of inline code tags Replace IComparer, IEqualityComparer, IEnumerable, Optional, IChangeSet, etc. with proper links for discoverability. --- src/DynamicData/Cache/ObservableCacheEx.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 761e5c2d3..119cb44aa 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -2905,7 +2905,7 @@ public static IObservable>> LimitSizeTo< /// OnErrorErrors from child observables are silently swallowed (the child is unsubscribed). Errors from the source changeset stream terminate the merged output. /// OnCompletedThe output completes only when the source completes and all active child observables have also completed. /// - /// Worth noting: The output is a plain IObservable<TDestination>, not a changeset stream. If you need merged changesets, use instead. + /// Worth noting: The output is a plain , not a changeset stream. If you need merged changesets, use instead. /// /// or is null. /// @@ -2956,9 +2956,9 @@ public static IObservable MergeMany(t /// /// Overload families: MergeChangeSets has 16 overloads organized along three axes: /// (1) Source type: dynamic (IObservable<IObservable<IChangeSet>>, sources arrive at runtime), - /// pair (source + other, exactly two streams), or static (IEnumerable, all sources known up front). - /// (2) Conflict resolution: none (first-in-wins), IComparer (lowest-ordered wins), - /// IEqualityComparer (suppresses duplicate updates), or both. + /// pair (source + other, exactly two streams), or static (, all sources known up front). + /// (2) Conflict resolution: none (first-in-wins), (lowest-ordered wins), + /// (suppresses duplicate updates), or both. /// (3) Completion: static overloads accept a completable flag; when false, the output never completes /// even after all sources finish (useful for "live" merge scenarios). /// @@ -4512,8 +4512,8 @@ public static void Remove(this IIntermediateCache } /// - /// Strips the key from a cache changeset, converting IChangeSet<TObject, TKey> to - /// IChangeSet<TObject> (list changeset). All indexed changes are dropped (sorting is not supported). + /// Strips the key from a cache changeset, converting to + /// (list changeset). All indexed changes are dropped (sorting is not supported). /// /// The type of the object. /// The type of the key. @@ -5171,7 +5171,7 @@ public static IObservable> ToObservableChangeSetThe source changeset stream. /// The key to watch. /// Optional comparer to suppress duplicate emissions. Uses default equality if null. - /// An observable of Optional<TObject> that reflects the presence or absence of the specified key. + /// An observable of that reflects the presence or absence of the specified key. /// /// /// Unlike , this emits None on removal From 13241c058d58b55e590a9b9129108b5ba46ff8a1 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 08:04:25 -0700 Subject: [PATCH 05/23] docs: add type links to all param descriptions in cache operators Every param tag now mentions and links its type via see/cref. Source params link to IObservable{T} and IChangeSet{TObject, TKey}, scheduler params link to IScheduler, predicate/factory params link to Func{T, TResult}, comparer params link to IComparer{T} and IEqualityComparer{T}, etc. --- .../Cache/ObservableCacheEx.SortAndBind.cs | 219 +- .../ObservableCacheEx.VirtualiseAndPage.cs | 195 +- src/DynamicData/Cache/ObservableCacheEx.cs | 5171 ++++++++--------- 3 files changed, 2569 insertions(+), 3016 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index 7cb3afb04..68e0edb9a 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -18,10 +18,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. + /// The source of . + /// The resulting read only observable collection. /// An observable which will emit change sets. - /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -39,11 +38,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. - /// Bind and sort default options. + /// The source of . + /// The resulting read only observable collection. + /// The Bind and sort default options. /// An observable which will emit change sets. - /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -62,10 +60,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. + /// The source of . + /// The list to bind to. /// An observable which will emit change sets. - /// This is the primary Bind overload for paged data. It applies paged changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -78,11 +75,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. - /// Bind and sort default options. + /// The source of . + /// The list to bind to. + /// The Bind and sort default options. /// An observable which will emit change sets. - /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -96,10 +92,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. + /// The source of . + /// The resulting read only observable collection. /// An observable which will emit change sets. - /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -117,11 +112,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. - /// Bind and sort default options. + /// The source of . + /// The resulting read only observable collection. + /// The Bind and sort default options. /// An observable which will emit change sets. - /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -140,10 +134,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. + /// The source of . + /// The list to bind to. /// An observable which will emit change sets. - /// This is the primary Bind overload for virtualized data. It applies virtualized changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -156,11 +149,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. - /// Bind and sort default options. + /// The source of . + /// The list to bind to. + /// The Bind and sort default options. /// An observable which will emit change sets. - /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -169,8 +161,14 @@ public static partial class ObservableCacheEx where TKey : notnull => new BindVirtualized(source, targetList, options).Run(); - /// - /// This overload uses for types implementing . + /// + /// Bind sorted data to the specified collection, for an object which implements IComparable>. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The list to bind to. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList) @@ -178,8 +176,15 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, DynamicDataOptions.SortAndBind); - /// - /// This overload uses for types implementing . + /// + /// Bind sorted data to the specified collection, for an object which implements IComparable>. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The list to bind to. + /// The Bind and sort default options. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -188,7 +193,15 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, Comparer.Default, options); - /// + /// + /// Bind sorted data to the specified collection. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The list to bind to. + /// An comparer to order the resulting dataset. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -198,34 +211,15 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparer, DynamicDataOptions.SortAndBind); /// - /// Sorts the source changeset using and applies incremental changes - /// directly to , keeping it sorted in-place. - /// Combines the behavior of Sort and Bind into a single optimized step. + /// Bind sorted data to the specified collection. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. - /// The comparer to order the resulting dataset. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The source of . + /// The list to bind to. + /// An comparer to order the resulting dataset. + /// The Bind and sort default options. /// An observable which will emit change sets. - /// - /// - /// This operator is the preferred replacement for the .Sort().Bind() chain. - /// It applies sort logic and collection mutations in a single pass, avoiding intermediate allocations. - /// - /// - /// EventBehavior - /// AddItem inserted at the correct sorted position in . - /// UpdateOld item removed and new item inserted at its sorted position. - /// RemoveItem removed from . - /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: Large batches may trigger a full list reset (clear + re-add) instead of incremental moves, controlled by . This fires CollectionChanged with Reset action, which can be more efficient for UI virtualization but causes a visual flicker. - /// - /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -235,7 +229,15 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparer, options, targetList).Run(); - /// + /// + /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The list to bind to. + /// An of which enables the sort order to be changed.> + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -245,33 +247,15 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparerChanged, DynamicDataOptions.SortAndBind); /// - /// Sorts the source changeset and applies incremental changes directly to , - /// re-sorting when the comparer observable emits a new comparer. + /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. - /// An observable of comparers which enables the sort order to be changed. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The source of . + /// The list to bind to. + /// An of which enables the sort order to be changed.> + /// The Bind and sort default options. /// An observable which will emit change sets. - /// - /// - /// When emits a new comparer, all items are re-sorted and the target list is updated. - /// No data is emitted until the first comparer arrives. - /// - /// - /// EventBehavior - /// AddItem inserted at the correct sorted position in . - /// UpdateOld item removed and new item inserted at its sorted position. - /// RemoveItem removed from . - /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. - /// Comparer changedFull re-sort of all items. The target list is updated to reflect the new order. - /// OnErrorForwarded to the downstream observer. - /// - /// Worth noting: No data is emitted until the comparer observable produces its first value. Large batches or comparer changes may trigger a full list reset depending on . - /// - /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -281,8 +265,14 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparerChanged, options, targetList).Run(); - /// - /// This overload uses for types implementing . + /// + /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -290,8 +280,15 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, DynamicDataOptions.SortAndBind); - /// - /// This overload uses for types implementing . + /// + /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// The Bind and sort default options. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -300,7 +297,15 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, options); - /// + /// + /// Bind sorted data to the specified readonly observable collection. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// An comparer to order the resulting dataset. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -309,11 +314,16 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparer, DynamicDataOptions.SortAndBind); - /// - /// The source changeset stream. - /// The resulting read only observable collection. - /// The comparer to order the resulting dataset. - /// Bind and sort options controlling reset threshold and initial capacity. + /// + /// Bind sorted data to the specified readonly observable collection. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// An comparer to order the resulting dataset. + /// The Bind and sort default options. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -332,7 +342,15 @@ public static partial class ObservableCacheEx return new SortAndBind(source, comparer, options, observableCollection).Run(); } - /// + /// + /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// An of which enables the sort order to be changed. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -341,11 +359,16 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparerChanged, DynamicDataOptions.SortAndBind); - /// - /// The source changeset stream. - /// The resulting read only observable collection. - /// An observable of comparers which enables the sort order to be changed. - /// Bind and sort options controlling reset threshold and initial capacity. + /// + /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The resulting read only observable collection. + /// An of which enables the sort order to be changed.> + /// The Bind and sort default options. + /// An observable which will emit change sets. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index 325fe8e4e..e6e30ecef 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -12,8 +12,16 @@ namespace DynamicData; /// public static partial class ObservableCacheEx { - /// - /// This overload uses default . + /// + /// Sort and virtualize the underlying data from the specified source. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An comparer to order the resulting dataset. + /// An of that specifies the virtualizing parameters. + /// An observable which will emit virtual change sets. + /// source. public static IObservable>> SortAndVirtualize(this IObservable> source, IComparer comparer, IObservable virtualRequests) @@ -21,8 +29,16 @@ public static IObservable>> So where TKey : notnull => source.SortAndVirtualize(comparer, virtualRequests, new SortAndVirtualizeOptions()); - /// - /// This overload uses default . + /// + /// Sort and virtualize the underlying data from the specified source. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of which enables the sort order to be changed.> + /// An of that specifies the virtualizing parameters. + /// An observable which will emit virtual change sets. + /// source. public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -37,35 +53,16 @@ public static IObservable>> So } /// - /// Sorts unsorted data using , then returns only items within the - /// virtual window defined by . + /// Sort and virtualize the underlying data from the specified source. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer to order the resulting dataset. - /// The virtualizing requests (start index and page size). - /// Additional optimization options for virtualization. + /// The source of . + /// An comparer to order the resulting dataset. + /// An of that specifies the virtualizing parameters. + /// The Addition optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. - /// - /// - /// Combines sorting and index-based windowing. Only items within the current virtual window are emitted. - /// Use the observable comparer overload if you need to change sort order at runtime. - /// - /// - /// EventBehavior - /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. - /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. - /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. - /// RefreshSort position is re-evaluated. Window membership may change. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No data is emitted until produces its first value. Changing the window can cause a full recalculation of visible items. - /// - /// - /// public static IObservable>> SortAndVirtualize( this IObservable> source, IComparer comparer, @@ -81,35 +78,16 @@ public static IObservable>> So } /// - /// Sorts unsorted data, then returns only the items within the virtual window defined by - /// (start index + size). Re-sorts when the comparer observable emits. + /// Sort and virtualize the underlying data from the specified source. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable of comparers which enables the sort order to be changed. - /// The virtualizing requests (start index and page size). - /// Additional optimization options for virtualization. + /// The source of . + /// An of which enables the sort order to be changed.> + /// An of that specifies the virtualizing parameters. + /// The Addition optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. - /// - /// - /// Combines sorting and index-based windowing in a single operator. Only items within the - /// current virtual window are emitted downstream. The window is defined by a start index and size. - /// - /// - /// EventBehavior - /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. - /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. - /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. - /// RefreshSort position is re-evaluated. Window membership may change. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No data is emitted until both the comparer observable and virtualRequests have produced their first values. Changing the window or comparer can cause a full recalculation of visible items. - /// - /// - /// public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -129,8 +107,8 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The virtualising requests. + /// The source of . + /// An of that specifies the virtualizing parameters. /// An observable which will emit virtual change sets. /// source. [Obsolete(Constants.VirtualizeIsObsolete)] @@ -145,25 +123,16 @@ public static IObservable> Virtualise - /// Returns the top items from the source, sorted by . - /// Equivalent to SortAndVirtualize with a fixed window starting at index 0. + /// Limits the size of the result set to the specified number, ordering by the comparer. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer. - /// The maximum number of items to return. + /// The source of . + /// An comparer. + /// The size. /// An observable which will emit virtual change sets. /// source. /// size;Size should be greater than zero. - /// - /// - /// Internally delegates to - /// with a fixed of (0, size). - /// - /// Worth noting: When the Nth item is displaced by a new item with higher sort priority, the displaced item is emitted as a Remove and the new item as an Add. - /// - /// public static IObservable>> Top(this IObservable> source, IComparer comparer, int size) where TObject : notnull where TKey : notnull @@ -184,7 +153,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// The size. /// An observable which will emit virtual change sets. /// source. @@ -204,8 +173,16 @@ public static IObservable> Top(t return new Virtualise(source, Observable.Return(new VirtualRequest(0, size))).Run(); } - /// - /// This overload uses default . + /// + /// Sort and page the underlying data from the specified source. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An comparer to order the resulting dataset. + /// An of that specifies the paging parameters. + /// An observable which will emit virtual change sets. + /// source. public static IObservable>> SortAndPage(this IObservable> source, IComparer comparer, IObservable pageRequests) @@ -213,8 +190,16 @@ public static IObservable>> SortA where TKey : notnull => source.SortAndPage(comparer, pageRequests, new SortAndPageOptions()); - /// - /// This overload uses default . + /// + /// Sort and page the underlying data from the specified source. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of which enables the sort order to be changed.> + /// An of that specifies the paging parameters. + /// An observable which will emit virtual change sets. + /// source. public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -229,34 +214,16 @@ public static IObservable>> SortA } /// - /// Sorts unsorted data using , then pages the result using - /// . + /// Sort and page the underlying data from the specified source. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer to order the resulting dataset. - /// The page requests (page number and page size). - /// Additional optimization options for paging. - /// An observable which will emit paged change sets. + /// The source of . + /// An comparer to order the resulting dataset. + /// An of that specifies the paging parameters. + /// The Addition optimization options for virtualization. + /// An observable which will emit virtual change sets. /// source. - /// - /// - /// Combines sorting and page-based windowing. Only items on the current page are emitted. - /// Use the observable comparer overload if you need to change sort order at runtime. - /// - /// - /// EventBehavior - /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. - /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. - /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. - /// RefreshSort position is re-evaluated. Page membership may change. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No data is emitted until produces its first value. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. - /// - /// public static IObservable>> SortAndPage( this IObservable> source, IComparer comparer, @@ -272,34 +239,16 @@ public static IObservable>> SortA } /// - /// Sorts unsorted data, then pages the result using page number and page size from - /// . Re-sorts when the comparer observable emits. + /// Sort and page the underlying data from the specified source. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable of comparers which enables the sort order to be changed. - /// The page requests (page number and page size). - /// Additional optimization options for paging. - /// An observable which will emit paged change sets. + /// The source of . + /// An of which enables the sort order to be changed.> + /// An of that specifies the paging parameters. + /// The Addition optimization options for virtualization. + /// An observable which will emit virtual change sets. /// source. - /// - /// - /// Combines sorting and page-based windowing in a single operator. Only items on the current page - /// are emitted downstream. The page is defined by a 1-based page number and page size. - /// - /// - /// EventBehavior - /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. - /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. - /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. - /// RefreshSort position is re-evaluated. Page membership may change. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No data is emitted until both the comparer observable and pageRequests have produced their first values. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. - /// - /// public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -319,8 +268,8 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The page requests. + /// The source of . + /// An of that specifies the paging parameters. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] public static IObservable> Page(this IObservable> source, IObservable pageRequests) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 119cb44aa..016ccceec 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -28,32 +28,18 @@ public static partial class ObservableCacheEx private const bool DefaultResortOnSourceRefresh = true; /// - /// Injects a side effect into the changeset stream by calling . - /// for every changeset, then forwarding it downstream unchanged. + /// Inject side effects into the stream using the specified adaptor. /// - /// The type of items in the cache. + /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The adaptor whose Adapt method is called for each changeset. - /// An observable that emits the same changesets as , after the adaptor has processed each one. - /// - /// - /// This is a thin wrapper around Rx's Do operator. The adaptor receives each changeset - /// as a side effect; the changeset itself is forwarded downstream unmodified. - /// - /// - /// EventBehavior - /// AddPassed to the adaptor, then forwarded. - /// UpdatePassed to the adaptor, then forwarded. - /// RemovePassed to the adaptor, then forwarded. - /// RefreshPassed to the adaptor, then forwarded. - /// OnErrorForwarded to the downstream observer. The adaptor is not called. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// or is null. - /// - /// + /// The source of . + /// The adaptor. + /// An observable which will emit change sets. + /// + /// source + /// or + /// destination. + /// public static IObservable> Adapt(this IObservable> source, IChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -64,10 +50,19 @@ public static IObservable> Adapt(this I return source.Do(adaptor.Adapt); } - /// - /// The source sorted changeset stream. - /// The sorted adaptor whose Adapt method is called for each sorted changeset. - /// This overload operates on . Delegates to Rx's Do operator. + /// + /// Inject side effects into the stream using the specified sorted adaptor. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The adaptor. + /// An observable which will emit change sets. + /// + /// source + /// or + /// destination. + /// public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -79,28 +74,13 @@ public static IObservable> Adapt(this I } /// - /// Adds or updates the cache with the specified item, producing a changeset with a single Add - /// (if the key is new) or Update (if the key already exists). + /// Adds or updates the cache with the specified item. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The item to add or update. - /// - /// Convenience method that wraps a single-item mutation inside . - /// - /// EventBehavior - /// AddProduced when the key does not already exist in the cache. - /// UpdateProduced when the key already exists. The previous value is included in the changeset. - /// RemoveNot produced by this method. - /// RefreshNot produced by this method. - /// OnErrorNot applicable (synchronous mutation). - /// OnCompletedNot applicable (synchronous mutation). - /// - /// - /// is null. - /// - /// + /// The source. + /// The item. + /// source. public static void AddOrUpdate(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -110,11 +90,15 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item)); } - /// - /// The source cache. - /// The item to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. - /// This overload uses to suppress no-op updates when the new value equals the existing one. + /// + /// Adds or updates the cache with the specified item. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// The item. + /// An equality comparer used to determine whether a new item is the same as an existing cached item. + /// source. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -124,10 +108,16 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item, equalityComparer)); } - /// - /// The source cache. - /// The items to add or update. - /// Batch overload. All items are added/updated inside a single call, producing one changeset. + /// + /// + /// Adds or updates the cache with the specified items. + /// + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// An items. + /// source. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -137,11 +127,17 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items)); } - /// - /// The source cache. - /// The items to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. - /// Batch overload with equality comparison. All items are added/updated inside a single call. + /// + /// + /// Adds or updates the cache with the specified items. + /// + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// An items. + /// An equality comparer used to determine whether a new item is the same as an existing cached item. + /// source. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -151,11 +147,15 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items, equalityComparer)); } - /// - /// The source intermediate cache. + /// + /// Adds or updates the cache with the specified item / key pair. + /// + /// The type of the object. + /// The type of the key. + /// The source cache. /// The item to add or update. - /// The key to associate with the item. - /// This overload operates on , which requires an explicit key parameter. + /// The key to add or update. + /// source. public static void AddOrUpdate(this IIntermediateCache source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -172,8 +172,8 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The others. + /// The source of . + /// The other of streams. /// An observable which emits change sets. /// source or others. public static IObservable> And(this IObservable> source, params IObservable>[] others) @@ -192,7 +192,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of of streams. source. /// An observable which emits change sets. /// /// source @@ -214,7 +214,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of of streams. source. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -231,7 +231,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -248,7 +248,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -260,14 +260,13 @@ public static IObservable> And(this IOb } /// - /// Wraps an in a read-only facade, hiding the mutable API. + /// Converts the source to an read only observable cache. /// /// The type of the object. /// The type of the key. - /// The source cache to wrap. - /// A read-only . - /// is null. - /// + /// The source. + /// An observable cache. + /// source. public static IObservableCache AsObservableCache(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -278,24 +277,14 @@ public static IObservableCache AsObservableCache(t } /// - /// Materializes a changeset stream into a queryable, read-only . - /// The cache subscribes to the source on first access and maintains a live snapshot of all items. + /// Converts the source to a readonly observable cache. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// If true (default), all cache operations are synchronized. Set to false when the caller guarantees single-threaded access. - /// A read-only observable cache that reflects the current state of the pipeline. - /// - /// - /// Disposing the returned cache unsubscribes from the source stream. The cache's Connect() - /// method provides a changeset stream of its own, which re-emits the current state on each new subscriber. - /// - /// When is false, a is used internally. - /// - /// is null. - /// - /// + /// The source of . + /// if set to true all methods are synchronised. There is no need to apply locking when the consumer can be sure the read / write operations are already synchronised. + /// An observable cache. + /// source. public static IObservableCache AsObservableCache(this IObservable> source, bool applyLocking = true) where TObject : notnull where TKey : notnull @@ -313,48 +302,34 @@ public static IObservableCache AsObservableCache(t #if SUPPORTS_ASYNC_DISPOSABLE /// /// - /// Disposes items implementing or when they are removed or replaced, - /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. + /// Automatically disposes items within the source collection, upon removal of the collection or teardown of the operator. /// /// - /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators - /// see the removal before disposal occurs. Items implementing neither disposal interface are ignored. + /// Individual items are disposed after removal or replacement changes have been sent downstream. + /// All items previously-published on the stream are disposed after the stream finalizes. + /// This includes both upstream completion or failure, or downstream un-subscription. /// - /// - /// The type of items in the cache. - /// The type of the key. - /// The source changeset stream. - /// /// - /// Invoked once per subscription, providing an that signals when all - /// calls have finished. The signal emits a single value - /// and then completes. + /// Disposal is supported for both and items. + /// Items implementing neither of these interfaces are unaffected by this operator. /// + /// + /// The type of items in the source collection. + /// The type of key values used to uniquely identify items in the source collection. + /// The source of . + /// /// - /// This is delivered on a separate channel from the main changeset stream so it can be observed even - /// if the source stream errors. + /// An to be invoked upon each subscription to this operator, allowing the consumer access to the "disposalsCompleted" stream for that subscription. /// - /// - /// A stream that forwards all changesets from unchanged. - /// /// - /// Change reason handling: - /// - /// EventBehavior - /// AddTracks the item. No disposal. - /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. - /// RemoveDisposes the removed item. - /// RefreshPassed through. No disposal. - /// + /// The "disposalsCompleted" stream allows the consumer to properly observe the asynchronous disposal of any items that are disposed by the operator. This stream will emit a single value, and then complete, upon successfull completion of all invocations performed by the operator. /// /// - /// On stream completion, error, or subscription disposal, all items still in the cache are disposed. - /// items are disposed synchronously; items - /// are dispatched via the signal. + /// Providing these notifications within a downstream channel separate from the main collection change stream ensures that these notifications can be observed even in the event of a failure within the operator, or within stream. /// - /// - /// or is null. - /// + /// + /// A stream containing copies of all changes observed from . + /// Throws for and . public static IObservable> AsyncDisposeMany( this IObservable> source, Action> disposalsCompletedAccessor) @@ -370,10 +345,10 @@ public static IObservable> AsyncDisposeMany /// The object of the change set. /// The key of the change set. - /// The source observable. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// The source of . Observable. + /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// A When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -401,11 +376,11 @@ public static IObservable> AutoRefresh( /// The object of the change set. /// The key of the change set. /// The type of the property. - /// The source observable. - /// Specify a property to observe changes. When it changes a Refresh is invoked. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// The source of . Observable. + /// An Specify a property to observe changes. When it changes a Refresh is invoked. + /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// A When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, Expression> propertyAccessor, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -433,10 +408,10 @@ public static IObservable> AutoRefreshThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source observable change set. - /// An observable which acts on items within the collection and produces a value when the item should be refreshed. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// The source of . Observable change set. + /// A observable which acts on items within the collection and produces a value when the item should be refreshed. + /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull @@ -448,14 +423,11 @@ public static IObservable> AutoRefreshOnObservableThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source observable change set. - /// An observable which acts on items within the collection and produces a value when the item should be refreshed. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// The source of . Observable change set. + /// A observable which acts on items within the collection and produces a value when the item should be refreshed. + /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The scheduler. /// An observable change set with additional refresh changes. - /// - /// Worth noting: Per-item observable errors are silently ignored (not forwarded to the downstream observer). Only source stream errors propagate. - /// public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -467,34 +439,17 @@ public static IObservable> AutoRefreshOnObservable - /// Collects changesets emitted within a time window and merges them into a single changeset. - /// Uses Rx's Buffer operator followed by . + /// Batches the updates for the specified time period. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The time window for batching. - /// The scheduler for timing. Defaults to . - /// An observable that emits merged changesets, one per time window. - /// - /// - /// All changesets received during the time window are concatenated into a single changeset. - /// This is useful for reducing UI update frequency when the source emits many rapid changes. - /// - /// - /// EventBehavior - /// AddBuffered and included in the merged changeset at the end of the time window. - /// UpdateBuffered and included in the merged changeset. - /// RemoveBuffered and included in the merged changeset. - /// RefreshBuffered and included in the merged changeset. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedAny remaining buffered changes are flushed, then completion is forwarded. - /// - /// Worth noting: The merged changeset may contain contradictory changes (e.g., Add then Remove for the same key). Downstream operators handle this correctly, but raw inspection of the changeset may be surprising. - /// - /// is null. - /// - /// + /// The source of . + /// A time span. + /// The scheduler. + /// An observable which emits change sets. + /// source + /// or + /// scheduler. public static IObservable> Batch(this IObservable> source, TimeSpan timeSpan, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -504,55 +459,66 @@ public static IObservable> Batch(this I return source.Buffer(timeSpan, scheduler ?? GlobalConfig.DefaultScheduler).FlattenBufferResult(); } - /// - /// This overload delegates to the primary overload with initialPauseState: false. + /// + /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. + /// When a resume signal has been received the batched updates will be fired. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. + /// The scheduler. + /// An observable which emits change sets. + /// source. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, scheduler); - /// - /// This overload delegates to the primary overload with default initialPauseState: false. + /// + /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. + /// When a resume signal has been received the batched updates will be fired. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. + /// if set to true [initial pause state]. + /// The scheduler. + /// An observable which emits change sets. + /// source. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, scheduler: scheduler).Run(); - /// - /// This overload omits initialPauseState (defaults to false) but accepts a timeout. + /// + /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. + /// When a resume signal has been received the batched updates will be fired. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. + /// A Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. + /// The scheduler. + /// An observable which emits change sets. + /// source. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, timeOut, scheduler); /// - /// Conditionally buffers changesets while a pause signal is active, then flushes all buffered - /// changes as a single merged changeset when the signal resumes. + /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. + /// When a resume signal has been received the batched updates will be fired. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// When true, buffering begins. When false, the buffer is flushed. - /// If true, starts in a paused (buffering) state. - /// Maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. - /// The scheduler for timeout timing. - /// An observable that emits changesets, buffered or passthrough depending on pause state. - /// - /// - /// While paused, incoming changesets are accumulated. On resume (or timeout), all buffered changesets - /// are merged into a single changeset and emitted. While not paused, changesets pass through immediately. - /// - /// - /// EventBehavior - /// AddBuffered while paused; forwarded immediately while active. - /// UpdateBuffered while paused; forwarded immediately while active. - /// RemoveBuffered while paused; forwarded immediately while active. - /// RefreshBuffered while paused; forwarded immediately while active. - /// OnErrorForwarded to the downstream observer. Buffered data is lost. - /// OnCompletedForwarded. Any remaining buffered data is flushed before completion. - /// - /// Worth noting: If the source completes while paused, buffered data IS flushed before OnCompleted. However, if the source errors while paused, buffered data is lost. - /// - /// or is null. - /// - /// + /// The source of . + /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. + /// if set to true [initial pause state]. + /// A Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. + /// The scheduler. + /// An observable which emits change sets. + /// source. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -563,13 +529,19 @@ public static IObservable> BatchIf(this return new BatchIf(source, pauseIfTrueSelector, timeOut, initialPauseState, scheduler: scheduler).Run(); } - /// - /// The source changeset stream. - /// When true, buffering begins. When false, the buffer is flushed. - /// If true, starts in a paused (buffering) state. - /// An observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. - /// The scheduler. - /// This overload accepts an explicit timer observable instead of a timeout. + /// + /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. + /// When a resume signal has been received the batched updates will be fired. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. + /// if set to true [initial pause state]. + /// An of Specify a time observable. The buffer will be emptied each time the timer produces a value and when it completes. On completion buffering will cease. + /// The scheduler. + /// An observable which emits change sets. + /// source. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IObservable? timer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, timer, scheduler).Run(); @@ -579,8 +551,8 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// The source of . + /// The destination. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. /// source. @@ -606,9 +578,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. - /// The binding options. + /// The source of . + /// The destination. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -625,9 +597,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. - /// The updater. + /// The source of . + /// The destination. + /// The updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, IObservableCollectionAdaptor updater) @@ -656,9 +628,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. - /// The binding options. + /// The source of . + /// The resulting read only observable collection. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -677,11 +649,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. + /// The source of . + /// The resulting read only observable collection. /// The number of changes before a reset notification is triggered. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// Specify an adaptor to change the algorithm to update the target collection. + /// The Specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, IObservableCollectionAdaptor? adaptor = null) @@ -713,8 +685,8 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// The source of . + /// The destination. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination) @@ -732,9 +704,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. - /// The binding options. + /// The source of . + /// The destination. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -753,9 +725,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. - /// The updater. + /// The source of . + /// The destination. + /// The updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, ISortedObservableCollectionAdaptor updater) @@ -784,9 +756,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. - /// The binding options. + /// The source of . + /// The resulting read only observable collection. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -807,11 +779,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The resulting read only observable collection. + /// The source of . + /// The resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// Specify an adaptor to change the algorithm to update the target collection. + /// The Specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, ISortedObservableCollectionAdaptor? adaptor = null) @@ -841,8 +813,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source changeset stream. - /// The target binding list. + /// The source of . + /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -865,8 +837,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source changeset stream. - /// The target binding list. + /// The source of . + /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -887,24 +859,14 @@ public static IObservable> Bind(this IO #endif /// - /// Buffers the initial burst of changesets for the specified duration, merges them into a single - /// changeset, then passes all subsequent changesets through without buffering. + /// Buffers changes for an initial period only. After the period has elapsed, not further buffering occurs. /// /// The object type. /// The type of the key. - /// The source change set. - /// The time window to buffer, measured from when the first changeset arrives. - /// The scheduler for timing. Defaults to . - /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. - /// - /// - /// Useful for aggregating the initial snapshot (which may arrive as many small changesets) into a - /// single changeset for efficient downstream processing, while leaving subsequent live updates untouched. - /// - /// Internally uses , Rx Buffer, and . - /// - /// - /// + /// The source of . Change set. + /// A period to buffer, measure from the time that the first item arrives. + /// The scheduler to buffer on. + /// An observable which emits change sets. public static IObservable> BufferInitial(this IObservable> source, TimeSpan initialBuffer, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => source.DeferUntilLoaded().Publish( @@ -916,28 +878,15 @@ public static IObservable> BufferInitial - /// Casts each item in the changeset to a new type using the provided converter function. - /// Equivalent to - /// but named for discoverability when a simple type cast or conversion is needed. + /// Cast the object to the specified type. + /// Alas, I had to add the converter due to type inference issues. /// - /// The type of the source object. + /// The type of the object. /// The type of the key. - /// The type of the destination object. - /// The source changeset stream. - /// The conversion function applied to each item. - /// An observable changeset of converted items. - /// - /// - /// EventBehavior - /// AddCalls and emits an Add with the converted item. - /// UpdateCalls on the new value and emits an Update. - /// RemoveEmits a Remove. The converter is not called. - /// RefreshForwarded as Refresh. The converter is not called. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// + /// The type of the destination. + /// The source of . + /// A conversion factory. + /// An observable which emits change sets. public static IObservable> Cast(this IObservable> source, Func converter) where TSource : notnull where TKey : notnull @@ -949,27 +898,14 @@ public static IObservable> Cast - /// Re-keys each item in the changeset by applying to the current item. - /// The original change reason is preserved; only the key is remapped. + /// Changes the primary key. /// /// The type of the object. /// The type of the source key. /// The type of the destination key. - /// The source changeset stream. - /// A function that computes the destination key from the item, e.g. (item) => item.NewId. - /// An observable changeset with items re-keyed using . - /// - /// - /// EventBehavior - /// Add is called on the item. An Add is emitted with the destination key. - /// Update is called on the current item. An Update is emitted with the destination key. If the key selector produces a different destination key for the updated value than it did for the original value, downstream consumers will see an Update for a key that may not match the original Add. - /// Remove is called on the item. A Remove is emitted with the destination key. - /// Refresh is called on the item. A Refresh is emitted with the destination key. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// + /// The source of . + /// A key selector eg. (item) => newKey. + /// An observable which emits change sets. public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -986,11 +922,16 @@ public static IObservable> ChangeKey - /// - /// This overload also provides the source key to , - /// allowing the destination key to be derived from both the item and its original key. - /// + /// + /// Changes the primary key. + /// + /// The type of the object. + /// The type of the source key. + /// The type of the destination key. + /// The source of . + /// A key selector eg. (key, item) => newKey. + /// An observable which emits change sets. + /// source. public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -1008,23 +949,12 @@ public static IObservable> ChangeKey - /// Removes all items from the cache, producing a changeset with a Remove for every item. + /// Clears all data. /// /// The type of the object. /// The type of the key. - /// The source cache to clear. - /// - /// - /// EventBehavior - /// AddNot produced by this operation. - /// UpdateNot produced by this operation. - /// RemoveA Remove is emitted for every item currently in the cache. - /// RefreshNot produced by this operation. - /// OnErrorNot applicable (synchronous mutation method). - /// OnCompletedNot applicable (synchronous mutation method). - /// - /// - /// is null. + /// The source. + /// source. public static void Clear(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -1034,7 +964,13 @@ public static void Clear(this ISourceCache source) source.Edit(updater => updater.Clear()); } - /// + /// + /// Clears all items from the cache. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// source. public static void Clear(this IIntermediateCache source) where TObject : notnull where TKey : notnull @@ -1044,7 +980,13 @@ public static void Clear(this IIntermediateCache s source.Edit(updater => updater.Clear()); } - /// + /// + /// Clears all data. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// source. public static void Clear(this LockFreeObservableCache source) where TObject : notnull where TKey : notnull @@ -1054,25 +996,13 @@ public static void Clear(this LockFreeObservableCache - /// Applies each change from the source changeset to the specified collection as a side effect. - /// The changeset is forwarded downstream unchanged. + /// Clones the changes into the specified collection. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The target collection to which changes are applied. - /// An observable that forwards all changesets from unchanged. - /// - /// - /// EventBehavior - /// AddThe item is added to . Forwarded as Add. - /// UpdateThe previous item is removed from and the current item is added. Forwarded as Update. - /// RemoveThe item is removed from . Forwarded as Remove. - /// RefreshIgnored ( has no concept of refresh). Forwarded as Refresh. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// + /// The source of . + /// The target. + /// An observable which emits change sets. public static IObservable> Clone(this IObservable> source, ICollection target) where TObject : notnull where TKey : notnull @@ -1111,13 +1041,14 @@ public static IObservable> Clone(this I } /// - /// Obsolete: use instead. + /// Convert the object using the specified conversion function. + /// This is a lighter equivalent of Transform and is designed to be used with non-disposable objects. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source changeset stream. - /// The conversion factory. + /// The source of . + /// A conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] public static IObservable> Convert(this IObservable> source, Func conversionFactory) @@ -1137,26 +1068,12 @@ public static IObservable> Convert - /// Suppresses all emissions until the first non-empty changeset arrives, then replays that changeset and all subsequent ones. - /// If the source never produces a non-empty changeset, the stream waits indefinitely. + /// Defer the subscription until the stream has been inflated with data. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable that begins emitting changesets once the first non-empty changeset is received. - /// - /// - /// EventBehavior - /// AddForwarded as Add once the initial non-empty changeset has been received. - /// UpdateForwarded as Update once loaded. - /// RemoveForwarded as Remove once loaded. - /// RefreshForwarded as Refresh once loaded. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: Blocks indefinitely if the cache or stream never receives any data. Ensure the source will eventually emit at least one changeset. - /// - /// + /// The source of . + /// An observable which emits change sets. public static IObservable> DeferUntilLoaded(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1166,7 +1083,13 @@ public static IObservable> DeferUntilLoaded(source).Run(); } - /// + /// + /// Defer the subscription until the stream has been inflated with data. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// An observable which emits change sets. public static IObservable> DeferUntilLoaded(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -1177,39 +1100,17 @@ public static IObservable> DeferUntilLoaded + /// Disposes each item when no longer required. /// - /// Disposes items implementing when they are removed or replaced, - /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. - /// - /// - /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators - /// see the removal before disposal occurs. Items that do not implement are ignored. + /// Individual items are disposed after removal or replacement changes have been sent downstream. + /// All items previously-published on the stream are disposed after the stream finalizes. /// /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// A stream that forwards all changesets from unchanged. - /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddTracks the item. No disposal. - /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. - /// RemoveDisposes the removed item. - /// RefreshPassed through. No disposal. - /// - /// - /// - /// On stream completion, error, or subscription disposal, all remaining tracked items are disposed. - /// All disposal is synchronous via . - /// For items that implement , use instead. - /// - /// - /// is null. - /// - /// + /// The source of . + /// A continuation of the original stream. + /// source. public static IObservable> DisposeMany(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1225,12 +1126,11 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// The value selector. + /// The source of . + /// A value selector. /// An observable which will emit distinct change sets. /// /// Due to it's nature only adds or removes can be returned. - /// Worth noting: Reference counting assumes value equality is transitive. Mutable value objects with inconsistent Equals implementations can corrupt ref counts. /// /// source. public static IObservable> DistinctValues(this IObservable> source, Func valueSelector) @@ -1244,14 +1144,16 @@ public static IObservable> DistinctValues>(observer => new DistinctCalculator(source, valueSelector).Run().SubscribeSafe(observer)); } - /// - /// The source cache to diff against. - /// The complete snapshot of items to diff against the cache. - /// An used to determine whether a new item is the same as an existing cached item. - /// - /// This overload uses an instead of a delegate - /// to determine item equality. - /// + /// + /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items + /// in the list and amends only the differences. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// An items to add, update or delete. + /// An equality comparer used to determine whether a new item is the same as an existing cached item. + /// source. public static void EditDiff(this ISourceCache source, IEnumerable allItems, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -1264,26 +1166,15 @@ public static void EditDiff(this ISourceCache sour } /// - /// Diffs a complete snapshot of items against the current cache contents, producing the minimal set of - /// Add, Update, and Remove changes needed to bring the cache in sync with the snapshot. + /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items + /// in the list and amends only the differences. /// /// The type of the object. /// The type of the key. - /// The source cache to diff against. - /// The complete snapshot of desired items. - /// A function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. - /// - /// - /// EventBehavior - /// AddItems in whose key is not in the cache produce an Add. - /// UpdateItems present in both and the cache that differ (per ) produce an Update. - /// RemoveItems in the cache whose key is not in produce a Remove. - /// RefreshNot produced by this operation. - /// OnErrorNot applicable (synchronous mutation method). - /// OnCompletedNot applicable (synchronous mutation method). - /// - /// - /// , , or is null. + /// The source. + /// An items to compare and add, update or delete. + /// A Expression to determine whether an item's value is equal to the old value (current, previous) => current.Version == previous.Version. + /// source. public static void EditDiff(this ISourceCache source, IEnumerable allItems, Func areItemsEqual) where TObject : notnull where TKey : notnull @@ -1297,29 +1188,15 @@ public static void EditDiff(this ISourceCache sour } /// - /// Converts an of into a changeset stream by diffing each - /// emission against the previous one. Each emission replaces the entire dataset. - /// Counterpart to . + /// Converts an Observable of Enumerable to an Observable ChangeSet that updates when the enumerables changes. Counterpart operator to . /// /// The type of the object. /// The type of the key. - /// The source observable of item snapshots. - /// A function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if null. - /// An observable changeset representing the incremental differences between successive snapshots. - /// - /// - /// EventBehavior - /// AddItems in the new snapshot whose key was not in the previous snapshot produce an Add. - /// UpdateItems present in both snapshots that differ (per ) produce an Update. - /// RemoveItems in the previous snapshot whose key is absent from the new snapshot produce a Remove. - /// RefreshNot produced by this operator. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// or is null. - /// + /// An of source. + /// A Key Selection Function for the ChangeSet. + /// Optional instance to use for comparing values. + /// An observable cache. + /// source. public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1331,27 +1208,15 @@ public static IObservable> EditDiff(thi } /// - /// Converts an of into a changeset stream that tracks - /// a single item: Some produces an Add or Update, and None produces a Remove. + /// Converts an Observable Optional to an Observable ChangeSet that adds/removes/updates as the optional changes. /// /// The type of the object. /// The type of the key. - /// The source observable of optional values. - /// A function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if null. - /// An observable changeset tracking the single optional item. - /// - /// - /// EventBehavior - /// AddEmitted when the source produces Some(value) and no item was previously tracked. - /// UpdateEmitted when the source produces Some(value) and an item was already tracked with a different value (per ). - /// RemoveEmitted when the source produces None and an item was previously tracked. - /// RefreshNot produced by this operator. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// or is null. + /// An source. + /// A Key Selection Function for the ChangeSet. + /// Optional instance to use for comparing values. + /// An observable changeset. + /// source. public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1363,24 +1228,12 @@ public static IObservable> EditDiff(thi } /// - /// Validates that each changeset contains no duplicate keys. - /// If duplicates are detected, an is emitted via OnError. + /// Ensures there are no duplicated keys in the observable changeset. /// + /// The source of . Change set. /// The type of the object. /// The type of the key. - /// The source changeset stream to validate. - /// A changeset stream guaranteed to contain unique keys per changeset. - /// - /// - /// EventBehavior - /// AddForwarded as Add if the key is unique within the changeset. - /// UpdateForwarded as Update if the key is unique within the changeset. - /// RemoveForwarded as Remove if the key is unique within the changeset. - /// RefreshForwarded as Refresh if the key is unique within the changeset. - /// OnErrorForwarded. Also emitted with if duplicate keys are detected in a changeset. - /// OnCompletedForwarded to the downstream observer. - /// - /// + /// A changeset which guarantees a key is only present at most once in the changeset. public static IObservable> EnsureUniqueKeys(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1396,8 +1249,8 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The others. + /// The source of . + /// The other of streams. /// An observable which emits change sets. /// /// source @@ -1424,7 +1277,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The sources. + /// An of of streams. sources. /// An observable which emits change sets. /// /// source @@ -1446,7 +1299,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of of streams. source. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1463,7 +1316,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1480,7 +1333,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1492,28 +1345,19 @@ public static IObservable> Except(this } /// - /// Schedules automatic removal of items after the timeout returned by . - /// If returns null, the item never expires. + /// Automatically removes items from the stream after the time specified by + /// the timeSelector elapses. Return null if the item should never be removed. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// An observable changeset that includes timer-driven Remove changes for expired items. - /// - /// When a timer fires, a Remove is emitted for the expired item. - /// - /// EventBehavior - /// AddSchedules a removal timer based on . Forwarded as Add. - /// UpdateResets the removal timer for the item. Forwarded as Update. - /// RemoveCancels the removal timer. Forwarded as Remove. - /// RefreshForwarded as Refresh. No timer change. - /// OnErrorForwarded. All pending timers are cancelled. - /// OnCompletedForwarded. All pending timers are cancelled. - /// - /// Worth noting: A null return from means "never expire". Update changes reset the expiration timer. - /// - /// or is null. + /// The source of . + /// A time selector. + /// An observable which emits change sets. + /// + /// source + /// or + /// timeSelector. + /// public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector) @@ -1523,10 +1367,21 @@ public static IObservable> ExpireAfter( source: source, timeSelector: timeSelector); - /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// The scheduler used to schedule expiration timers. + /// + /// Automatically removes items from the stream after the time specified by + /// the timeSelector elapses. Return null if the item should never be removed. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// A time selector. + /// The scheduler. + /// An observable which emits change sets. + /// + /// source + /// or + /// timeSelector. + /// public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1538,15 +1393,21 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, scheduler: scheduler); - /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. - /// This is less accurate but more efficient when many items share similar expiration times. - /// - /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next - /// poll after their timeout elapses, which trades accuracy for reduced timer overhead. - /// + /// + /// Automatically removes items from the stream on the next poll after the time specified by + /// the time selector elapses. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// A time selector. Return null if the item should never be removed. + /// A polling interval. If this value is specified, items are expired on an interval. + /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. + /// + /// An observable of enumerable of the key values which has been removed. + /// source + /// or + /// timeSelector. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1558,11 +1419,22 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, pollingInterval: pollingInterval); - /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. - /// The scheduler used to schedule polling and expiration timers. + /// + /// Automatically removes items from the stream on the next poll after the time specified by + /// the time selector elapses. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// A time selector. Return null if the item should never be removed. + /// A polling interval. If this value is specified, items are expired on an interval. + /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. + /// + /// The scheduler. + /// An observable of enumerable of the key values which has been removed. + /// source + /// or + /// timeSelector. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1577,22 +1449,21 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// Automatically removes items from the after the timeout returned - /// by . Returns an observable of the removed key-value pairs (not a changeset stream). + /// Automatically removes items from the cache after the time specified by + /// the time selector elapses. /// /// The type of the object. /// The type of the key. - /// The source cache from which expired items are removed. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. - /// The scheduler used to schedule expiration timers. Defaults to if null. - /// An observable that emits the key-value pairs of items removed from the cache by expiration. - /// - /// Unlike the stream-based overloads, this operates directly on the - /// and returns the removed items as collections, - /// not as a changeset stream. - /// - /// or is null. + /// The cache. + /// A time selector. Return null if the item should never be removed. + /// A polling interval. Since multiple timer subscriptions can be expensive, + /// it may be worth setting the interval. + /// + /// The scheduler. + /// An observable of enumerable of the key values which has been removed. + /// source + /// or + /// timeSelector. public static IObservable>> ExpireAfter( this ISourceCache source, Func timeSelector, @@ -1607,29 +1478,14 @@ public static IObservable>> ExpireAfter< scheduler: scheduler); /// - /// Filters items from the source changeset stream using a static predicate. - /// Only items that satisfy are included downstream. + /// Filters the specified source. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The predicate used to determine whether each item is included. - /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets, which can be useful for monitoring loading status. - /// An observable changeset containing only items that satisfy . - /// - /// - /// EventBehavior - /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. - /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. - /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. - /// RefreshThe predicate is re-evaluated. If the item now passes but previously did not, an Add is emitted. If it still passes, a Refresh is forwarded. If it no longer passes, a Remove is emitted. If it still fails, the change is dropped. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: Refresh events trigger re-evaluation, which can promote or demote items. Pair with for property-change-driven filtering. - /// - /// - /// + /// The source of . + /// A filter. + /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. + /// An observable which emits change sets. public static IObservable> Filter( this IObservable> source, Func filter, @@ -1641,11 +1497,15 @@ public static IObservable> Filter( filter: filter, suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// - /// This overload does not accept a reapplyFilter signal. It is equivalent to calling the - /// full dynamic overload with as the reapply observable. - /// + /// + /// Creates a filtered stream which can be dynamically filtered. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of . Observable to change the underlying predicate. + /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. + /// An observable which emits change sets. public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1658,34 +1518,19 @@ public static IObservable> Filter( suppressEmptyChangeSets: suppressEmptyChangeSets); /// - /// Creates a dynamically filtered stream where the filter predicate depends on external state. - /// Each emission from triggers a full re-filtering of all items. + /// Creates a filtered stream which can be dynamically filtered, based on state values passed through to a static filtering predicate. /// /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source changeset stream. - /// A stream of state values to be passed to . - /// A predicate that receives the current state and an item, returning true to include or false to exclude. - /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets. - /// An observable changeset containing only items satisfying for the latest state. - /// , , or is null. + /// The source of . + /// An stream of state values to be passed to . + /// A static predicate to be used to determine which items should be included or excluded by the filter. + /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. + /// An observable which emits change sets. + /// Throws for , , and . /// - /// - /// should emit an initial value immediately upon subscription. - /// Until the first state value arrives, no items pass the filter (all items are excluded). - /// Each subsequent state emission triggers a full re-evaluation of every item in the collection. - /// - /// - /// EventBehavior - /// AddEvaluated against the current state. If it passes, an Add is emitted. Otherwise dropped. - /// UpdateRe-evaluated. Four outcomes as with the static overload. - /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. - /// RefreshRe-evaluated against the current state. May produce Add, Refresh, Remove, or be dropped. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: should emit an initial value immediately. Each emission triggers a full re-evaluation of all items, which can be expensive for large collections. + /// Usually, should emit an initial value, immediately upon subscription. This is because cannot be invoked until the first state value is received, and accordingly, the operator will treat all items as excluded until then. Each value emitted by will trigger a full re-filtering of the entire collection. /// public static IObservable> Filter( this IObservable> source, @@ -1701,17 +1546,16 @@ public static IObservable> Filter(), suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// The source changeset stream. - /// An observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. - /// An observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. - /// When true (default), empty changesets are suppressed for performance. - /// - /// In addition to the per-item behavior described in the static overload, - /// emissions from replace the predicate and trigger full re-filtering, - /// while emissions from re-evaluate all items against the current predicate. - /// Worth noting: No items are included until the predicate observable emits its first value. - /// + /// + /// Creates a filtered stream which can be dynamically filtered. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An of . Observable to change the underlying predicate. + /// An of Observable to re-evaluate whether the filter still matches items. Use when filtering on mutable values. + /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. + /// An observable which emits change sets. public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1732,8 +1576,8 @@ public static IObservable> Filter( /// /// The type of collection items to be filtered. /// The type of the key values of each collection item. - /// The source stream of collection items to be filtered. - /// The filtering predicate to be applied to each item. + /// The source of . Stream of collection items to be filtered. + /// A filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. /// @@ -1747,15 +1591,6 @@ public static IObservable> Filter( /// Your filtering predicate runs quickly, and does not heavily allocate memory /// /// Note that, because filtering is purely deterministic, Refresh operations are transparently ignored by this operator. - /// - /// EventBehavior - /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. - /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. - /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. - /// RefreshDropped. Because items are assumed immutable, there is nothing to re-evaluate. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// /// public static IObservable> FilterImmutable( this IObservable> source, @@ -1775,48 +1610,16 @@ public static IObservable> FilterImmutable - /// Filters items using a per-item that controls inclusion. - /// Each item's observable is created by and toggles the item in or out of the downstream stream. + /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// A factory that creates an for each item and its key. When the observable emits true, the item is included; when false, it is excluded. - /// Optional time window to buffer inclusion changes from per-item observables before re-evaluating. - /// Optional scheduler used for buffering. - /// An observable changeset containing only items whose per-item observable most recently emitted true. - /// - /// - /// Source changeset handling (parent events): - /// - /// - /// EventBehavior - /// AddSubscribes to the per-item observable. The item is not included downstream until the observable emits its first true. - /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. Inclusion state is reset; the new observable must emit before the item reappears. - /// RemoveDisposes the item's observable subscription. If the item was included downstream, a Remove is emitted. - /// RefreshForwarded as Refresh if the item is currently included downstream. Otherwise dropped. - /// - /// - /// Per-item observable handling (filter observable events): - /// - /// - /// EmissionBehavior - /// First trueThe item is included: an Add is emitted downstream. - /// false (was included)The item is excluded: a Remove is emitted downstream. - /// true (was excluded)The item is re-included: an Add is emitted downstream. - /// true (was included)No effect (already included). - /// false (was excluded)No effect (already excluded). - /// ErrorTerminates the entire output stream. - /// CompletedThe item remains in its current inclusion state. No further toggling is possible for this item. - /// - /// - /// Worth noting: Items are invisible downstream until their per-item observable emits at least one true. - /// If an item's observable never emits, the item never appears. The parameter batches - /// rapid inclusion changes from per-item observables into a single re-evaluation, reducing changeset chatter. - /// - /// - /// or is null. - /// + /// The source of . + /// A Factory function used to create the observable bool that controls whether that given item passes the filter or not. + /// A Optional time to buffer changes from the observable bools. + /// The Optional scheduler to use when buffering the changes. + /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. + /// One of the given parameters was null. public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1827,10 +1630,17 @@ public static IObservable> FilterOnObservable(source, filterFactory, buffer, scheduler).Run(); } - /// - /// - /// This overload does not provide the key to ; only the item is passed. - /// + /// + /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// A Factory function used to create the observable bool that controls whether that given item passes the filter or not. + /// A Optional time to buffer changes from the observable bools. + /// The Optional scheduler to use when buffering the changes. + /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. + /// One of the given parameters was null. public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1842,12 +1652,13 @@ public static IObservable> FilterOnObservable - /// Obsolete: do not use. This can cause unhandled exception issues. Use the standard Rx Finally operator instead. + /// Ensure that finally is always called. Thanks to Lee Campbell for this. /// /// The type contained within the observables. - /// The source changeset stream. - /// The finally action. + /// An source. + /// An finally action. /// An observable which has always a finally action applied. + /// source. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) { @@ -1858,15 +1669,13 @@ public static IObservable FinallySafe(this IObservable source, Action f } /// - /// Unwraps each into individual - /// values via . + /// Flattens an update collection to it's individual items. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable of individual values. - /// is null. - /// + /// The source of . + /// An observable which emits change set values on a flatten result. + /// source. public static IObservable> Flatten(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1877,14 +1686,12 @@ public static IObservable> Flatten(this IOb } /// - /// Merges a list of changesets (typically from an Rx Buffer operation) into a single changeset - /// by concatenating all changes. Empty buffers are filtered out. + /// Convert the result of a buffer operation to a single change set. /// /// The type of the object. /// The type of the key. - /// The source observable of buffered changeset lists. - /// An observable changeset combining all changes from each buffer into a single emission. - /// is null. + /// An source. + /// An observable which emits change sets. public static IObservable> FlattenBufferResult(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -1895,29 +1702,13 @@ public static IObservable> FlattenBufferResult - /// Invokes for every individual in each changeset, - /// regardless of change reason. The changeset is forwarded downstream unchanged. + /// Provides a call back for each change. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The action to invoke for each change. Receives the full struct, including , , , and . - /// A stream that forwards all changesets from unchanged. - /// - /// - /// All change reasons (Add, Update, Remove, Refresh) trigger the callback. - /// Use , - /// , - /// , or - /// - /// to target a specific reason. - /// - /// - /// Implemented via Rx's Do operator on the changeset stream. - /// Exceptions thrown in propagate as OnError to the subscriber. No try-catch is applied. - /// - /// - /// or is null. + /// The source of . + /// An action. + /// An observable which will perform the action on each item. public static IObservable> ForEachChange(this IObservable> source, Action> action) where TObject : notnull where TKey : notnull @@ -1928,12 +1719,20 @@ public static IObservable> ForEachChange changes.ForEach(action)); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the optional left and right values into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. + /// This is the equivalent of SQL full join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1950,48 +1749,19 @@ public static IObservable> FullJoin - /// Joins two changeset streams, producing a result for every key that appears on either side (or both). - /// Both sides are because a given key may only exist on one side at any point. - /// Equivalent to SQL FULL OUTER JOIN. + /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. + /// This is the equivalent of SQL full join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). - /// An observable changeset keyed by . - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddEmits with the left value and the matching right (or Optional.None if no right exists). - /// UpdateRe-invokes with the new left value and current right (if any). - /// RemoveIf a right match still exists, re-invokes the selector with left as Optional.None. If neither side remains, removes the joined result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddEmits with the matching left (or Optional.None) and the right value. - /// UpdateRe-invokes selector with current left (if any) and the new right value. - /// RemoveIf a left match still exists, re-invokes the selector with right as Optional.None. If neither side remains, removes the joined result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2007,12 +1777,20 @@ public static IObservable> FullJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. + /// This is the equivalent of SQL full join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2029,49 +1807,19 @@ public static IObservable> FullJoinMany - /// Groups right-side items by their mapped key, then full-joins each group to the left source. - /// A result is produced for every key that appears on either side (or both). The left value is - /// because only the right side may have entries for a given key. - /// Equivalent to SQL FULL OUTER JOIN with the right side grouped. + /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. + /// This is the equivalent of SQL full join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). - /// An observable changeset keyed by . - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddEmits with the left value and the current right group for that key (may be empty). - /// UpdateRe-invokes with the new left value and current right group. - /// RemoveIf the right group is non-empty, re-invokes with left as Optional.None. If both sides are empty, removes the result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddUpdates the right group, then re-invokes selector with the current left (if any) and the updated group. - /// UpdateUpdates the right group and re-invokes selector. - /// RemoveUpdates the right group. If the group becomes empty and no left exists, removes the result. Otherwise re-invokes selector. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2088,16 +1836,16 @@ public static IObservable> FullJoinMany - /// Groups items from the source changeset, producing groups only for group keys present in . - /// Useful for parent-child relationships where parents and children come from different streams. + /// Groups the source on the value returned by group selector factory. + /// A group is included for each item in the resulting group source. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The group selector factory. + /// The source of . + /// A group selector factory. /// - /// A distinct stream used to determine the result. + /// An of used to determine the result groups. /// /// /// Useful for parent-child collection when the parent and child are soured from different streams. @@ -2116,38 +1864,14 @@ public static IObservable> Group - /// Groups items from the source changeset by a key extracted via . - /// Each group is an observable sub-cache that receives changes for its members. + /// Groups the source on the value returned by group selector factory. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Extracts the group key from each item. - /// An observable that emits group changesets. Each group exposes a sub-cache of its members. - /// - /// - /// Items are assigned to groups based on the value returned by . - /// Groups are created on demand when the first item is assigned, and removed when their last member is removed. - /// - /// - /// EventBehavior - /// AddThe group key is evaluated. The item is added to the corresponding group (creating the group if new). An Add is emitted to the group's sub-cache. - /// UpdateThe group key is re-evaluated. If unchanged, an Update is emitted within the same group. If the key changed, the item is removed from the old group (emitting Remove) and added to the new group (emitting Add). An empty old group is removed. - /// RemoveThe item is removed from its group. If the group becomes empty, the group itself is removed from the output. - /// RefreshThe group key is re-evaluated. If unchanged, a Refresh is forwarded within the group. If the key changed, the item moves between groups (Remove from old, Add to new). - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// Worth noting: Each group is a live sub-cache that can be subscribed to independently. Subscribers - /// to a group receive only changes for items in that group. When a group is removed (becomes empty), - /// its sub-cache completes. - /// - /// - /// - /// - /// + /// The source of . + /// A group selector key. + /// An observable which will emit group change sets. public static IObservable> Group(this IObservable> source, Func groupSelectorKey) where TObject : notnull where TKey : notnull @@ -2159,12 +1883,23 @@ public static IObservable> Group(source, groupSelectorKey, null).Run(); } - /// - /// The source changeset stream. - /// Extracts the group key from each item. - /// When this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. - /// An observable that emits group changesets. - /// This overload adds a signal. When it fires, every item in the cache is re-grouped using the current selector, which is useful when the grouping depends on mutable item state. + /// + /// Groups the source on the value returned by group selector factory. + /// + /// The type of the object. + /// The type of the key. + /// The type of the group key. + /// The source of . + /// A group selector key. + /// An of Invoke to the for the grouping to be re-evaluated. + /// An observable which will emit group change sets. + /// + /// source + /// or + /// groupSelectorKey + /// or + /// groupController. + /// public static IObservable> Group(this IObservable> source, Func groupSelectorKey, IObservable regrouper) where TObject : notnull where TKey : notnull @@ -2178,34 +1913,22 @@ public static IObservable> Group - /// Groups items using a dynamically changing group selector function. - /// Each time emits a new selector, all items are re-grouped. + /// Groups the source on the value returned by the latest value from the group selector factory observable. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// An observable that emits group selector functions. Each emission triggers a full re-grouping of all items. - /// Optional signal to force re-evaluation of all items against the current selector. - /// An observable that emits group changesets. - /// - /// - /// Unlike the static-selector overload, this accepts an observable of selector functions. When a new selector - /// arrives, every item is re-evaluated and may move between groups. The optional - /// signal triggers re-evaluation without changing the selector (useful when item properties that affect grouping change). - /// - /// - /// EventBehavior - /// AddThe current selector determines the group. Item is added to the group (group created if new). - /// UpdateGroup key re-evaluated. Item may move between groups if the key changed. - /// RemoveItem removed from its group. Empty groups are removed. - /// RefreshGroup key re-evaluated. Item may move between groups. - /// OnErrorForwarded from source or from . - /// OnCompletedForwarded when the source completes. - /// - /// - /// - /// + /// The source of . + /// An of . group selector key observable. + /// An of Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. + /// An observable which will emit group change sets. + /// + /// source + /// or + /// groupSelectorKey + /// or + /// groupController. + /// public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -2217,11 +1940,23 @@ public static IObservable> Group(source, groupSelectorKeyObservable, regrouper).Run(); } - /// - /// The source changeset stream. - /// An observable of selector functions that take only the item (not the key). - /// Optional signal to force re-evaluation. - /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. + /// + /// Groups the source on the value returned by the latest value from the group selector factory observable. + /// + /// The type of the object. + /// The type of the key. + /// The type of the group key. + /// The source of . + /// An of . group selector key observable. + /// An of Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. + /// An observable which will emit group change sets. + /// + /// source + /// or + /// groupSelectorKey + /// or + /// groupController. + /// public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -2233,52 +1968,14 @@ public static IObservable> Group - /// Groups items where each item's group key is determined by a per-item observable. - /// The observable is created by for each item. + /// Groups the source by the latest value from their observable created by the given factory. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Factory that creates a group key observable for each item and its key. - /// An observable that emits group changesets. Each group is a live sub-cache of its members. - /// - /// - /// Unlike which evaluates - /// the group key synchronously, this operator defers group assignment until the per-item observable emits. - /// - /// - /// Source changeset handling (parent events): - /// - /// - /// EventBehavior - /// AddSubscribes to the per-item group key observable. The item is not placed in any group until the observable emits its first group key. - /// UpdateDisposes the old item's group key subscription and subscribes to the new item's observable. The item is removed from its current group until the new observable emits. - /// RemoveDisposes the item's group key subscription. The item is removed from its current group. Empty groups are removed. - /// RefreshNo effect on subscriptions. The item remains in its current group. - /// - /// - /// Per-item observable handling (group key observable events): - /// - /// - /// EmissionBehavior - /// First valueThe item is placed into the group matching the emitted key. An Add appears in that group's sub-cache. If the group is new, the group itself is added to the output. - /// New value (different key)The item moves: Remove from the old group, Add to the new group. If the old group becomes empty, it is removed from the output. - /// Same value (unchanged key)No effect (filtered by DistinctUntilChanged). - /// ErrorTerminates the entire output stream. - /// CompletedThe item remains in its current group. No further group key changes are possible for this item. - /// - /// - /// Worth noting: Items are invisible (not in any group) until their per-item observable emits at least one - /// group key. If an item's observable never emits, the item never appears in any group. Per-item observable errors - /// terminate the entire stream. The output completes when the source completes and all per-item observables have - /// also completed. - /// - /// - /// - /// - /// - /// + /// The source of . + /// A group selector key. + /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull where TKey : notnull @@ -2296,8 +1993,8 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The group selector key. + /// The source of . + /// A group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull @@ -2316,10 +2013,10 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// The source of . + /// An property selector used to group the items. + /// A time span that indicates the throttle to wait for property change events. + /// The scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnProperty(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2339,10 +2036,10 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// The source of . + /// An property selector used to group the items. + /// A time span that indicates the throttle to wait for property change events. + /// The scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnPropertyWithImmutableState(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2356,35 +2053,22 @@ public static IObservable> Gr } /// - /// Groups items by , emitting immutable group snapshots instead of mutable sub-caches. - /// Each group change contains a frozen copy of the group's state at that point in time. + /// Groups the source on the value returned by group selector factory. Each update produces immutable grouping. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Extracts the group key from each item. - /// Optional signal to force re-evaluation of all items against the group selector. - /// An observable that emits immutable group changesets. - /// - /// - /// Behaves identically to - /// in terms of how items are assigned to groups, but each group emission is an immutable snapshot. - /// This makes it safe for parallel processing and eliminates race conditions on group state. - /// The tradeoff is higher memory usage, since each change produces a new snapshot of the affected group. - /// - /// - /// EventBehavior - /// AddItem added to its group. An immutable snapshot of the group is emitted. - /// UpdateIf group key unchanged, group snapshot re-emitted. If changed, item moves between groups; both affected groups emit new snapshots. - /// RemoveItem removed from group. Updated snapshot emitted. Empty groups are removed. - /// RefreshGroup key re-evaluated. If changed, item moves; affected group snapshots emitted. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// - /// - /// + /// The source of . + /// A group selector key. + /// An of Invoke to the for the grouping to be re-evaluated. + /// An observable which will emit immutable group change sets. + /// + /// source + /// or + /// groupSelectorKey + /// or + /// groupController. + /// public static IObservable> GroupWithImmutableState(this IObservable> source, Func groupSelectorKey, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -2401,7 +2085,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// The source observable which emits change sets. + /// The source of . Observable which emits change sets. /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2413,8 +2097,8 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The ignore function (current,previous)=>{ return true to ignore }. + /// The source of . + /// A ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) where TObject : notnull @@ -2440,8 +2124,8 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The include function (current,previous)=>{ return true to include }. + /// The source of . + /// A include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) where TObject : notnull @@ -2458,12 +2142,20 @@ public static IObservable> IncludeUpdateWhen - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the left and right values into a destination object. The composite key is not provided in this overload. - /// Overload that omits the composite key from the result selector. Delegates to . + /// + /// Joins the left and right observable data sources, taking values when both left and right values are present + /// This is the equivalent of SQL inner join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2480,48 +2172,19 @@ public static IObservable> IncludeUpdateWhen - /// Joins two changeset streams, producing a result only for keys that exist on both sides simultaneously. - /// When either side loses its value for a key, the joined result is removed. Equivalent to SQL INNER JOIN. + /// Groups the right data source and joins the to the left and the right sources, taking values when both left and right values are present + /// This is the equivalent of SQL inner join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). - /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddIf a matching right value exists, invokes and emits an Add. If no right match, no emission. - /// UpdateIf a matching right exists, re-invokes the selector and emits an Update. - /// RemoveRemoves all joined results involving the removed left key. - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddIf a matching left value exists, invokes the selector and emits an Add. - /// UpdateIf a matching left exists, re-invokes the selector and emits an Update. - /// RemoveRemoves the joined result for this right key (if it was downstream). - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// The output is keyed by a (TLeftKey, TRightKey) composite tuple, since a single left item may match multiple right items. - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func<(TLeftKey leftKey, TRightKey rightKey), TLeft, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2537,12 +2200,20 @@ public static IObservable> IncludeUpdateWhen(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the left value and the right group into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. + /// This is the equivalent of SQL inner join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2559,48 +2230,19 @@ public static IObservable> InnerJoinMany - /// Groups right-side items by their mapped key, then inner-joins each group to the left source. - /// A result is produced only when a left item and at least one right item share the same key. - /// Equivalent to SQL INNER JOIN with the right side grouped. + /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. + /// This is the equivalent of SQL inner join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). - /// An observable changeset keyed by . - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddIf a non-empty right group exists for this key, invokes and emits an Add. Otherwise no emission. - /// UpdateIf a right group exists, re-invokes the selector and emits an Update. - /// RemoveRemoves the joined result (if it was downstream). - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddUpdates the right group. If a matching left exists and the group was previously empty, emits an Add. If already joined, emits an Update. - /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. - /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2617,34 +2259,29 @@ public static IObservable> InnerJoinMany - /// Calls Evaluate() on items that implement when a Refresh change arrives. - /// Other change reasons are forwarded without invoking Evaluate. + /// Invokes Refresh method for an object which implements IEvaluateAware. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable that emits the same changesets as , unchanged. - /// - /// - /// EventBehavior - /// AddForwarded unchanged. - /// UpdateForwarded unchanged. - /// RemoveForwarded unchanged. - /// RefreshCalls Evaluate() on the item, then forwards the change. - /// OnErrorForwarded to subscribers. - /// OnCompletedForwarded to subscribers. - /// - /// + /// The source of . + /// An observable which emits change sets. public static IObservable> InvokeEvaluate(this IObservable> source) where TObject : IEvaluateAware where TKey : notnull => source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the left value and the optional right into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Joins the left and right observable data sources, taking all left values and combining any matching right values. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2661,48 +2298,18 @@ public static IObservable> LeftJoin - /// Joins two changeset streams, producing a result for every left-side key. The right side is - /// because a matching right item may or may not exist. All left items - /// appear in the output regardless. Equivalent to SQL LEFT OUTER JOIN. + /// Joins the left and right observable data sources, taking all left values and combining any matching right values. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). - /// An observable changeset keyed by . - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddAlways emits. Invokes with the left value and matching right (or Optional.None). - /// UpdateRe-invokes the selector with the new left value and current right (if any). - /// RemoveRemoves the joined result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddIf a matching left exists, re-invokes the selector (right transitions from None to Some) and emits an Update. - /// UpdateIf a matching left exists, re-invokes the selector with the new right value. - /// RemoveIf a matching left exists, re-invokes the selector (right transitions from Some to None) and emits an Update. - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2718,12 +2325,20 @@ public static IObservable> LeftJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the left value and the right group into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. + /// This is the equivalent of SQL left join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2740,48 +2355,19 @@ public static IObservable> LeftJoinMany - /// Groups right-side items by their mapped key, then left-joins each group to the left source. - /// A result is produced for every left-side key. The right group may be empty if no right items match. - /// Equivalent to SQL LEFT OUTER JOIN with the right side grouped. + /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. + /// This is the equivalent of SQL left join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). - /// An observable changeset keyed by . - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddAlways emits. Invokes with the left value and the current right group (which may be empty). - /// UpdateRe-invokes the selector with the new left value and current right group. - /// RemoveRemoves the joined result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddUpdates the right group. If a matching left exists, re-invokes the selector and emits an Update. - /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. - /// RemoveUpdates the right group. If a matching left exists, re-invokes the selector (group may now be empty). - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2798,27 +2384,16 @@ public static IObservable> LeftJoinMany - /// Applies a FIFO size limit to the changeset stream. When the number of items exceeds , - /// the oldest items are evicted and emitted as Remove changes. + /// Applies a size limiter to the number of records which can be included in the + /// underlying cache. When the size limit is reached the oldest items are removed. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The maximum number of items allowed. Must be greater than zero. - /// An observable changeset stream with size-limited contents. - /// - /// - /// EventBehavior - /// AddForwarded. If the cache exceeds the size limit, the oldest items are emitted as Remove changes. - /// UpdateForwarded unchanged. - /// RemoveForwarded unchanged. - /// RefreshForwarded unchanged. - /// OnErrorForwarded to subscribers. - /// OnCompletedForwarded to subscribers. - /// - /// - /// is null. - /// is zero or negative. + /// The source of . + /// The size. + /// An observable which emits change sets. + /// source. + /// size cannot be zero. public static IObservable> LimitSizeTo(this IObservable> source, int size) where TObject : notnull where TKey : notnull @@ -2834,17 +2409,17 @@ public static IObservable> LimitSizeTo( } /// - /// Operates directly on a , removing the oldest items when the cache - /// exceeds . Returns an observable of the evicted key-value pairs (not a changeset stream). + /// Limits the number of records in the cache to the size specified. When the size is reached + /// the oldest items are removed from the cache. /// /// The type of the object. /// The type of the key. - /// The source cache to apply the size limit to. - /// The maximum number of items allowed. Must be greater than zero. - /// Optional scheduler for observing changes. Defaults to . - /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. - /// is null. - /// is zero or negative. + /// The source. + /// The size limit. + /// The scheduler. + /// An observable which emits the key value pairs. + /// source. + /// Size limit must be greater than zero. public static IObservable>> LimitSizeTo(this ISourceCache source, int sizeLimit, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -2879,38 +2454,18 @@ public static IObservable>> LimitSizeTo< } /// - /// Subscribes to a child observable for each item in the source cache changeset stream and merges all child - /// emissions into a single . When an item is added, - /// creates its child subscription. When updated, the previous child subscription is disposed and a new one is created. - /// When removed, its child subscription is disposed. Refresh changes have no effect on subscriptions. + /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item + /// when it is no longer part of the stream. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of values emitted by child observables. - /// The source cache changeset stream. - /// Factory function that produces a child observable for each source item. - /// An observable that emits values from all active child observables, interleaved by arrival order. - /// - /// - /// This operator does not produce changesets. It produces a flat stream of - /// values, similar to Rx SelectMany but lifecycle-aware: child subscriptions track items entering and - /// leaving the source cache. - /// - /// - /// EventBehavior - /// AddCalls to create a child observable and subscribes to it. Emissions from the child flow into the merged output. - /// UpdateDisposes the previous child subscription and creates a new one for the updated item. - /// RemoveDisposes the child subscription for the removed item. - /// RefreshNo effect on subscriptions. The child observable continues unchanged. - /// OnErrorErrors from child observables are silently swallowed (the child is unsubscribed). Errors from the source changeset stream terminate the merged output. - /// OnCompletedThe output completes only when the source completes and all active child observables have also completed. - /// - /// Worth noting: The output is a plain , not a changeset stream. If you need merged changesets, use instead. - /// - /// or is null. - /// - /// - /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . + /// A observable selector. + /// An observable which emits the transformed value. + /// source + /// or + /// observableSelector. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2921,9 +2476,19 @@ public static IObservable MergeMany(t return new MergeMany(source, observableSelector).Run(); } - /// - /// The source cache changeset stream. - /// Factory function that receives both the item and its key, and returns a child observable. + /// + /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item + /// when it is no longer part of the stream. + /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . + /// A observable selector. + /// An observable which emits the transformed value. + /// source + /// or + /// observableSelector. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2935,52 +2500,13 @@ public static IObservable MergeMany(t } /// - /// Merges multiple changeset streams that arrive dynamically into a single unified changeset stream. - /// Each inner stream emitted by the outer observable is subscribed and its changes forwarded downstream. - /// When multiple sources provide the same key, the first source to add it retains priority unless a - /// comparer-based overload is used. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// A unified changeset stream containing changes from all active source streams. - /// - /// - /// Each inner changeset stream is independently tracked in its own cache. When multiple sources provide the same key, - /// this overload uses first-in-wins semantics: the value from whichever source added the key first is - /// the one published downstream. To control which value wins for duplicate keys, use an overload that - /// accepts an , which selects the lowest-ordered value across all sources. - /// An can be provided separately to suppress no-op updates when - /// the new value equals the currently published value for a key. - /// - /// - /// Overload families: MergeChangeSets has 16 overloads organized along three axes: - /// (1) Source type: dynamic (IObservable<IObservable<IChangeSet>>, sources arrive at runtime), - /// pair (source + other, exactly two streams), or static (, all sources known up front). - /// (2) Conflict resolution: none (first-in-wins), (lowest-ordered wins), - /// (suppresses duplicate updates), or both. - /// (3) Completion: static overloads accept a completable flag; when false, the output never completes - /// even after all sources finish (useful for "live" merge scenarios). - /// - /// - /// EventBehavior - /// AddIf no source has previously provided this key, an Add is emitted downstream. If another source already holds this key, the new value is tracked internally but not emitted (first-in-wins). With a comparer, the lowest-ordered value across all sources is selected and published instead. - /// UpdateIf the updating source currently owns the downstream value for this key, an Update is emitted. If a comparer is provided and the update causes a different source's value to become the best candidate, an Update is emitted with that other source's value. - /// RemoveIf the removed value was the one published downstream, the operator scans all remaining sources for the same key. If another source still holds that key, an Update is emitted with the replacement value (selected by comparer if provided, otherwise the next available). If no other source holds the key, a Remove is emitted. - /// RefreshIf the refreshed item matches the currently published value, the Refresh is forwarded. With a comparer, all sources are re-evaluated first; if a different value now wins, an Update is emitted instead of the Refresh. - /// OnErrorAn error from any source (outer or inner) terminates the entire merged output. - /// OnCompletedFor dynamic overloads, the output completes when the outer observable completes and all subscribed inner observables have also completed. For static overloads, completion depends on the completable parameter (default true). - /// - /// - /// Worth noting: When a source removes a key that was published downstream, the fallback to another - /// source's value is emitted as an Update (not an Add). This can be surprising if you expect - /// a Remove followed by an Add. Also, errors from any single inner source terminate the entire merged - /// stream, so consider error handling within individual sources if isolation is needed. - /// - /// - /// is null. - /// - /// + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -2991,16 +2517,14 @@ public static IObservable> MergeChangeSets - /// Merges dynamic cache changeset streams into a single output, using a comparer to resolve key conflicts. - /// When multiple sources provide the same key, the item ordering lowest according to - /// is published downstream. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// A unified changeset stream containing changes from all active source streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable>> source, IComparer comparer) where TObject : notnull where TKey : notnull @@ -3012,16 +2536,14 @@ public static IObservable> MergeChangeSets - /// Merges dynamic cache changeset streams into a single output, using an equality comparer to suppress - /// redundant updates. When an incoming value for a key is equal (per ) - /// to the currently published value, the update is suppressed. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// A unified changeset stream containing changes from all active source streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine if two elements are the same. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -3033,16 +2555,15 @@ public static IObservable> MergeChangeSets - /// Merges dynamic cache changeset streams into a single output, using both a comparer for key conflict resolution - /// and an equality comparer to suppress redundant updates. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// A unified changeset stream containing changes from all active source streams. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine if two elements are the same. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer, IComparer comparer) where TObject : notnull where TKey : notnull @@ -3055,17 +2576,16 @@ public static IObservable> MergeChangeSets - /// Convenience overload that merges exactly two cache changeset streams into a single output. - /// Uses first-in-wins semantics for key conflicts. + /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from both sources. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// The other of streams. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3077,17 +2597,17 @@ public static IObservable> MergeChangeSets - /// Convenience overload that merges exactly two cache changeset streams, using a comparer for key conflict resolution. + /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . - /// Comparer to determine which value wins when both sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from both sources. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// The other of streams. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3100,17 +2620,17 @@ public static IObservable> MergeChangeSets - /// Convenience overload that merges exactly two cache changeset streams, using an equality comparer to suppress redundant updates. + /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from both sources. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// The other of streams. + /// instance to determine if two elements are the same. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3123,18 +2643,18 @@ public static IObservable> MergeChangeSets - /// Convenience overload that merges exactly two cache changeset streams, using both a comparer and an equality comparer. + /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Comparer to determine which value wins when both sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from both sources. - /// , , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// The other of streams. + /// instance to determine if two elements are the same. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3148,17 +2668,16 @@ public static IObservable> MergeChangeSets - /// Merges with additional changeset streams into a single output. - /// Uses first-in-wins semantics for key conflicts. + /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The primary changeset stream. - /// Additional changeset streams to merge with . - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from all sources. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// An of of streams. Other Observable ChangeSets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3170,17 +2689,17 @@ public static IObservable> MergeChangeSets - /// Merges with additional changeset streams, using a comparer for key conflict resolution. + /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The primary changeset stream. - /// Additional changeset streams to merge with . - /// Comparer to determine which value wins when multiple sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from all sources. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// An of of streams. Other Observable ChangeSets. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3193,17 +2712,17 @@ public static IObservable> MergeChangeSets - /// Merges with additional changeset streams, using an equality comparer to suppress redundant updates. + /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The primary changeset stream. - /// Additional changeset streams to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from all sources. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// An of of streams. Other Observable ChangeSets. + /// instance to determine if two elements are the same. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3216,18 +2735,18 @@ public static IObservable> MergeChangeSets - /// Merges with additional changeset streams, using both a comparer and an equality comparer. + /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The primary changeset stream. - /// Additional changeset streams to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Comparer to determine which value wins when multiple sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. - /// A unified changeset stream containing changes from all sources. - /// , , , or is null. + /// The type of the object. + /// The type of the key. + /// The source of . Observable ChangeSet. + /// An of of streams. Other Observable ChangeSets. + /// instance to determine if two elements are the same. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3241,27 +2760,15 @@ public static IObservable> MergeChangeSets - /// Merges a fixed collection of cache changeset streams into a single unified output. All source streams are - /// subscribed when the output observable is subscribed to. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The collection of changeset streams to merge. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. - /// A unified changeset stream containing changes from all source streams. - /// - /// - /// When multiple sources provide items with the same key, this overload uses first-in-wins semantics: - /// the first source to provide a key retains priority. Removing that source's item allows the next - /// available value for that key (if any) to surface. To control which value wins, use an overload - /// that accepts an . - /// - /// - /// An error from any source terminates the entire merged output. - /// - /// - /// is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3272,18 +2779,16 @@ public static IObservable> MergeChangeSets - /// Merges a fixed collection of cache changeset streams into a single output, using a comparer for key conflict - /// resolution. When multiple sources provide the same key, the item ordering lowest according to - /// is published downstream. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The collection of changeset streams to merge. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. - /// A unified changeset stream containing changes from all source streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3295,18 +2800,16 @@ public static IObservable> MergeChangeSets - /// Merges a fixed collection of cache changeset streams into a single output, using an equality comparer to - /// suppress redundant updates. When an incoming value for a key is equal (per ) - /// to the currently published value, the update is suppressed. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The collection of changeset streams to merge. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. - /// A unified changeset stream containing changes from all source streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine if two elements are the same. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3318,18 +2821,17 @@ public static IObservable> MergeChangeSets - /// Merges a fixed collection of cache changeset streams into a single output, using both a comparer for key - /// conflict resolution and an equality comparer to suppress redundant updates. + /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. /// - /// The type of items in the changesets. - /// The type of the key identifying items. - /// The collection of changeset streams to merge. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// Optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. - /// A unified changeset stream containing changes from all source streams. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// An of of streams. Source Observable ChangeSet. + /// instance to determine if two elements are the same. + /// instance to determine which element to emit if the same key is emitted from multiple changesets. + /// (Optional) instance to use when enumerating the collection. + /// Whether or not the result Observable should complete if all the changesets complete. + /// The result from merging the changesets together. + /// Parameter was null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -3342,19 +2844,17 @@ public static IObservable> MergeChangeSets - /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes - /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. - /// The selector receives only the item, not its key. + /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. - /// A merged changeset stream containing items from all active child streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -3367,18 +2867,17 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes - /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. + /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. - /// A merged changeset stream containing items from all active child streams. - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -3393,19 +2892,18 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes - /// into a single flattened output. The selector receives only the item, not its key. + /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. - /// A merged changeset stream containing items from all active child streams. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -3419,65 +2917,18 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child changeset stream and merges all child - /// changes into a single flattened output stream. Child subscriptions track the parent item lifecycle: - /// created on Add, replaced on Update, disposed on Remove. + /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. /// - /// The type of items in the source (parent) cache. - /// The type of the key identifying parent items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream whose items each produce a child changeset stream. - /// Factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. - /// Optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. - /// Optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. - /// A merged changeset stream containing all child items from all active parent subscriptions. - /// - /// - /// This is the changeset-aware counterpart to . - /// Where MergeMany produces a flat IObservable<T>, MergeManyChangeSets produces an IObservable<IChangeSet> - /// that tracks the full lifecycle of child items, including key conflict resolution across parents. - /// - /// - /// Parent-side change handling (source changeset events): - /// - /// - /// EventBehavior - /// AddCalls with the new parent item to obtain a child changeset stream, then subscribes. As the child stream emits changesets, those child items are merged into the output. The downstream observer sees Add changes for each new child item. - /// UpdateDisposes the previous parent's child subscription (removing all of its contributed child items from the output as Remove changes), then creates a new child subscription for the updated parent. The new child's items appear as Add changes. - /// RemoveDisposes the parent's child subscription. All child items contributed by that parent are emitted as Remove changes in the output. If another parent also provides a child with the same destination key, that parent's value is promoted as an Update (not an Add). - /// RefreshNo effect on the child subscription. The parent's child stream continues unchanged. - /// - /// - /// Child-side change handling (changes arriving from child changeset streams): - /// - /// - /// EventBehavior - /// AddIf the destination key is new, an Add is emitted. If another parent already contributed a child with the same key, the conflict is resolved by (lowest wins) or first-in-wins if no comparer. The losing value is tracked internally but not emitted. - /// UpdateIf this parent currently owns the destination key downstream, an Update is emitted. With a comparer, all parents are re-evaluated for that key; a different parent's value may win, producing an Update to that value instead. - /// RemoveIf this parent's value was the one published downstream for that destination key, the operator scans other parents for the same key. If found, an Update is emitted with the replacement. If not, a Remove is emitted. - /// RefreshIf the child item is the one currently published downstream, the Refresh is forwarded. With a comparer, all parents are re-evaluated first; if a different value now wins, an Update is emitted instead. - /// - /// - /// Error and completion: - /// - /// - /// EventBehavior - /// OnErrorAn error from the source (parent) stream or from any child changeset stream terminates the entire output. Unlike , child errors are NOT swallowed. - /// OnCompletedThe output completes when the source (parent) stream completes and all active child changeset streams have also completed. - /// - /// - /// Worth noting: When multiple parents contribute children with the same destination key, only one value is published - /// downstream at a time. The controls which value wins; without it, the first parent to add the key - /// retains priority. Removing a parent that owned a contested key causes the next-best value (per comparer or next available) - /// to surface as an Update, not an Add. The independently controls whether a child - /// Update for an already-published key is suppressed when the new value equals the old. - /// - /// - /// or is null. - /// - /// - /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -3491,21 +2942,19 @@ public static IObservable> MergeManyCh } /// - /// Source-priority variant of MergeManyChangeSets with a required . - /// Uses to resolve destination key conflicts by source priority. - /// The selector receives only the item, not its key. - /// Source priorities are always re-evaluated on Refresh (default behavior). + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3519,20 +2968,19 @@ public static IObservable> MergeManyCh } /// - /// Source-priority variant of MergeManyChangeSets with a required . - /// Uses to resolve destination key conflicts by source priority. - /// Source priorities are always re-evaluated on Refresh (default behavior). + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3540,20 +2988,20 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Source-priority variant of MergeManyChangeSets with a required and - /// explicit control. The selector receives only the item. - /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3567,20 +3015,20 @@ public static IObservable> MergeManyCh } /// - /// Source-priority variant of MergeManyChangeSets with a required and - /// explicit control. + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3588,21 +3036,20 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, resortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Source-priority variant of MergeManyChangeSets. Uses to resolve - /// destination key conflicts. The selector receives only the item, not its key. - /// Source priorities are always re-evaluated on Refresh (default behavior). - /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional instance to determine if two elements are the same. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3616,20 +3063,20 @@ public static IObservable> MergeManyCh } /// - /// Source-priority variant of MergeManyChangeSets. Uses to resolve - /// destination key conflicts. Source priorities are always re-evaluated on Refresh (default behavior). + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional instance to determine if two elements are the same. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3637,21 +3084,21 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer, childComparer); /// - /// Source-priority variant of MergeManyChangeSets with full control over all conflict resolution parameters. - /// The selector receives only the item, not its key. - /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. - /// A merged changeset stream with conflicts resolved by source priority. - /// or is null. + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. + /// Optional instance to determine if two elements are the same. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3665,33 +3112,21 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child - /// changes into a single flattened output. When multiple source items produce children with the same destination key, - /// determines which source has priority (the source ordering lower wins). - /// If sources compare equal, (if provided) breaks the tie. + /// Overload of that + /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child changeset streams. - /// The type of the key identifying child items. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// Optional fallback comparer to resolve destination key conflicts when source items compare equal. - /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. - /// - /// - /// The provides a layer of conflict resolution above the child values themselves. - /// This is useful when source items represent priority tiers (e.g., user settings overriding defaults). - /// - /// - /// Errors from child streams propagate to the output. An error from the source or any child terminates the merged output. - /// The output completes when the source completes and all active child streams have also completed. - /// - /// - /// , , or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The type of the destination key. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// instance to determine which source elements child to use when two sources provide a child element with the same key. + /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. + /// Optional instance to determine if two elements are the same. + /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. + /// The result from merging the child changesets together. + /// Parameter was null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3706,17 +3141,15 @@ public static IObservable> MergeManyCh } /// - /// For each item in the source cache, subscribes to a child list changeset stream produced by - /// and merges all child changes into a single flattened list changeset output. - /// Child subscriptions follow the source item lifecycle: created on Add, replaced on Update, disposed on Remove. + /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child list changeset streams. - /// The source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child list changeset stream. - /// Optional equality comparer to detect duplicate items in the merged list output. - /// A merged list changeset stream containing items from all active child streams. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// Optional instance to determine if two elements are the same. + /// The result from merging the child changesets together. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3729,16 +3162,15 @@ public static IObservable> MergeManyChangeSets - /// For each item in the source cache, subscribes to a child list changeset stream and merges all child changes - /// into a single flattened list changeset output. The selector receives only the item, not its key. + /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of items in the child list changeset streams. - /// The source cache changeset stream. - /// Factory function that receives a source item and returns a child list changeset stream. - /// Optional equality comparer to detect duplicate items in the merged list output. - /// A merged list changeset stream containing items from all active child streams. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . Observable ChangeSet. + /// A Factory Function used to create child changesets. + /// Optional instance to determine if two elements are the same. + /// The result from merging the child changesets together. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3749,17 +3181,18 @@ public static IObservable> MergeManyChangeSets - /// Like , - /// but wraps each emitted value as an , pairing the source item - /// with the value it produced. This lets you identify which source item is responsible for each emission. + /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item + /// when it is no longer part of the stream. /// - /// The type of items in the source cache. - /// The type of the key identifying source cache items. - /// The type of values emitted by child observables. - /// The source cache changeset stream. - /// Factory function that produces a child observable for each source item. - /// An observable of pairing each emission with its source item. - /// or is null. + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . + /// A observable selector. + /// An observable which emits the item with the value. + /// source + /// or + /// observableSelector. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3770,9 +3203,19 @@ public static IObservable> MergeManyItems(source, observableSelector).Run(); } - /// - /// The source cache changeset stream. - /// Factory function that receives both the item and its key, and returns a child observable. + /// + /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item + /// when it is no longer part of the stream. + /// + /// The type of the object. + /// The type of the key. + /// The type of the destination. + /// The source of . + /// A observable selector. + /// An observable which emits the item with the value. + /// source + /// or + /// observableSelector. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3784,26 +3227,22 @@ public static IObservable> MergeManyItems - /// Monitors the source observable and emits values: Pending initially, - /// Loaded when the first value arrives, Errored on error, and Completed on completion. - /// This is not a changeset operator. + /// Monitors the status of a stream. /// /// The type of the source observable. - /// The source observable to monitor. - /// An observable that emits values reflecting the source's lifecycle. - /// is null. - /// + /// An source. + /// An observable which monitors the status of the observable. + /// source. public static IObservable MonitorStatus(this IObservable source) => new StatusMonitor(source).Run(); /// - /// Filters out empty changesets from the stream. A thin wrapper around Where(changes => changes.Count != 0). + /// Suppresses updates which are empty. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable that emits only non-empty changesets. - /// is null. - /// + /// The source of . + /// An observable which emits change set values when not empty. + /// source. public static IObservable> NotEmpty(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3814,27 +3253,16 @@ public static IObservable> NotEmpty(thi } /// - /// Filters and casts items in the changeset to . Items that are not of type - /// are excluded. Combines filter and transform in one step without an intermediate cache. + /// Filters an observable changeset so that it only includes items that are of type . /// /// The type of the objects in the source changeset. /// The type of the key. - /// The destination type to filter and cast to. - /// The source observable changeset. - /// If true, changesets that become empty after filtering are suppressed. - /// An observable changeset of items. - /// - /// - /// EventBehavior - /// AddIf the item is , cast and emit as Add. Otherwise dropped. - /// UpdateRe-evaluated. If the new item is , emit accordingly. If the old item was downstream but the new one is not, emit Remove. - /// RemoveIf the item was downstream, emit Remove. - /// RefreshIf the item is downstream, forwarded as Refresh. - /// OnErrorForwarded to subscribers. - /// OnCompletedForwarded to subscribers. - /// - /// - /// is null. + /// The type of the objects that are allowed to pass the filter. + /// The source of . Observable changeset of instances. + /// Indicates whether or not to suppress changesets that end up being empty after the conversion. + /// An observable changeset of where each item was either converted from or filtered out. + /// source. + /// Combines a filter and a transform into a single step that does not use an intermediate cache. public static IObservable> OfType(this IObservable> source, bool suppressEmptyChangeSets = true) where TObject : notnull where TKey : notnull @@ -3850,28 +3278,9 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each added item. Receives the new item and its key. - /// A stream that forwards all changesets from unchanged. - /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddInvokes with the item and key. - /// UpdateIgnored. - /// RemoveIgnored. - /// RefreshIgnored. - /// - /// - /// - /// Exceptions thrown in propagate as OnError. No try-catch is applied. - /// - /// - /// or is null. - /// - /// - /// + /// The source of . + /// An add action that takes the new value and the associated key. + /// An observable which emits a change set with items being added. public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3882,10 +3291,15 @@ public static IObservable> OnItemAdded( return source.OnChangeAction(ChangeReason.Add, addAction); } - /// - /// The source changeset stream. - /// The callback invoked for each added item. Receives only the item (no key). - /// Overload that omits the key from the callback. Delegates to . + /// + /// Callback for each item as and when it is being added to the stream. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An add action that takes the new value. + /// An observable which emits a change set with items being added. + /// Overload for with a callback that doesn't use a key. public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3896,26 +3310,9 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each refreshed item. Receives the item and its key. - /// A stream that forwards all changesets from unchanged. - /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddIgnored. - /// UpdateIgnored. - /// RemoveIgnored. - /// RefreshInvokes with the item and key. - /// - /// - /// - /// Exceptions thrown in propagate as OnError. No try-catch is applied. - /// - /// - /// or is null. - /// + /// The source of . + /// An refresh action that takes the refreshed value and the key. + /// An observable which emits a change set with items being added. public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull @@ -3926,54 +3323,34 @@ public static IObservable> OnItemRefreshed - /// The source changeset stream. - /// The callback invoked for each refreshed item. Receives only the item (no key). - /// Overload that omits the key from the callback. Delegates to . + /// + /// Callback for each item as and when it is being refreshed in the stream. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An refresh action that takes the refreshed value. + /// An observable which emits a change set with items being added. + /// Overload for with a callback that doesn't use a key. public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull => source.OnItemRefreshed((obj, _) => refreshAction(obj)); /// - /// Invokes for each item with in the changeset stream. - /// The changeset is forwarded downstream unchanged. + /// Callback for each item/key as and when it is being removed from the stream. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each removed item. Receives the removed item and its key. - /// - /// When true (the default), the callback is also invoked for every item still in the cache - /// when the subscription is disposed. When false, only inline Remove changes trigger the callback. - /// - /// A stream that forwards all changesets from unchanged. - /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddIgnored (but tracked internally when is true). - /// UpdateIgnored (cache updated internally when is true). - /// RemoveInvokes with the item and key. - /// RefreshIgnored. - /// - /// - /// - /// Unsubscribe behavior: when is true, the operator - /// maintains an internal cache mirroring the stream. On disposal, it iterates all remaining items and - /// invokes for each. This is useful for cleanup logic (e.g. event unsubscription) - /// that must run for items that were never explicitly removed. - /// - /// - /// Exceptions thrown in propagate as OnError during inline removes. - /// During unsubscribe disposal, exceptions are not caught. - /// - /// Worth noting: The action also fires for ALL remaining items when the subscription is disposed (unless invokeOnUnsubscribe is false). The action runs under a lock; avoid calling into other caches from within it. - /// - /// or is null. - /// - /// + /// The source of . + /// An remove action that takes the removed value and the key. + /// Should the remove action be invoked when the subscription is disposed. + /// An observable which emits a change set with items being removed. + /// + /// source + /// or + /// removeAction. + /// public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull @@ -3989,43 +3366,34 @@ public static IObservable> OnItemRemoved - /// The source changeset stream. - /// The callback invoked for each removed item. Receives only the item (no key). - /// When true (the default), also invoked for all remaining items on disposal. - /// Overload that omits the key from the callback. Delegates to . + /// + /// Callback for each item as and when it is being removed from the stream. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An remove action that takes the removed value. + /// Should the remove action be invoked when the subscription is disposed. + /// An observable which emits a change set with items being removed. + /// + /// source + /// or + /// removeAction. + /// + /// Overload for with a callback that doesn't use the key. public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull => source.OnItemRemoved((obj, _) => removeAction(obj), invokeOnUnsubscribe); /// - /// Invokes for each item with in the changeset stream. - /// The changeset is forwarded downstream unchanged. + /// Callback when an item has been updated eg. (current, previous)=>{}. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each updated item. Receives the current value, previous value, and key. - /// A stream that forwards all changesets from unchanged. - /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddIgnored. - /// UpdateInvokes with (current, previous, key). The previous value is always available for Update changes. - /// RemoveIgnored. - /// RefreshIgnored. - /// - /// - /// - /// Exceptions thrown in propagate as OnError. No try-catch is applied. - /// - /// - /// or is null. - /// - /// + /// The source of . + /// An update action that takes current value, previous value, and the key. + /// An observable which emits a change set with items being updated. public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull @@ -4036,43 +3404,33 @@ public static IObservable> OnItemUpdated change.Reason == ChangeReason.Update, change => updateAction(change.Current, change.Previous.Value, change.Key)); } - /// - /// The source changeset stream. - /// The callback invoked for each updated item. Receives only the current and previous values (no key). - /// Overload that omits the key from the callback. Delegates to . + /// + /// Callback when an item has been updated eg. (current, previous)=>{}. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// An update action that takes the current value and previous value. + /// An observable which emits a change set with items being updated. + /// Overload for with a callback that doesn't use the key. public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull => source.OnItemUpdated((cur, prev, _) => updateAction(cur, prev)); /// - /// Combines multiple changeset streams using logical OR (union). An item appears downstream if it exists in any source. + /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. /// /// The type of the object. /// The type of the key. - /// The first source changeset stream. - /// Additional changeset streams to combine with. - /// A changeset stream containing items present in any of the sources. - /// - /// - /// Items are tracked via reference counting across all sources. An item appears downstream as long as - /// at least one source contains it. When the last source holding a key removes it, the item is removed downstream. - /// - /// - /// EventBehavior - /// AddIf this is the first source to provide the key, an Add is emitted. If other sources already have the key, the reference count is incremented but no emission occurs. - /// UpdateIf the item is currently downstream, an Update is emitted. - /// RemoveReference count decremented. If the count reaches zero (no source holds the key), a Remove is emitted. Otherwise no emission. - /// RefreshIf the item is downstream, a Refresh is forwarded. - /// OnErrorAn error from any source terminates the combined output. - /// OnCompletedThe output completes when all sources have completed. - /// - /// - /// or is null. - /// - /// - /// - /// + /// The source of . + /// The other of streams. + /// An observable which emits change sets. + /// + /// source + /// or + /// others. + /// public static IObservable> Or(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -4087,9 +3445,18 @@ public static IObservable> Or(this IObs return source.Combine(CombineOperator.Or, others); } - /// - /// A fixed collection of changeset streams to combine. - /// This overload accepts a pre-built collection of sources instead of a params array. + /// + /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. + /// + /// The type of the object. + /// The type of the key. + /// An of of streams. source. + /// An observable which emits change sets. + /// + /// source + /// or + /// others. + /// public static IObservable> Or(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -4105,7 +3472,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of of streams. source. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -4122,7 +3489,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4139,7 +3506,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4151,19 +3518,18 @@ public static IObservable> Or(this IObs } /// - /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted batch of items. + /// Populate a cache from an observable stream. /// /// The type of the object. /// The type of the key. - /// The source cache to populate. - /// The observable that emits batches of items. - /// An that, when disposed, unsubscribes from . - /// - /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. - /// - /// or is null. - /// - /// + /// The source. + /// An of observable. + /// A disposable which will unsubscribe from the source. + /// + /// source + /// or + /// keySelector. + /// public static IDisposable PopulateFrom(this ISourceCache source, IObservable> observable) where TObject : notnull where TKey : notnull @@ -4174,14 +3540,18 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted item. + /// Populate a cache from an observable stream. /// /// The type of the object. /// The type of the key. - /// The source cache to populate. - /// The observable that emits individual items. - /// An that, when disposed, unsubscribes from . - /// or is null. + /// The source. + /// An observable. + /// A disposable which will unsubscribe from the source. + /// + /// source + /// or + /// keySelector. + /// public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) where TObject : notnull where TKey : notnull @@ -4192,30 +3562,18 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Subscribes to the changeset stream and clones each changeset into the destination cache. + /// Populates a source into the specified cache. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination cache to populate. - /// An that, when disposed, unsubscribes from the source. - /// - /// - /// Each changeset from the source is applied to the destination cache inside an Edit call. - /// - /// - /// EventBehavior - /// AddThe item is added to the destination cache via AddOrUpdate. - /// UpdateThe item is updated in the destination cache via AddOrUpdate. - /// RemoveThe item is removed from the destination cache. - /// RefreshA Refresh is issued on the destination cache for the item. - /// OnErrorThe subscription is terminated. The destination cache is not rolled back. - /// OnCompletedThe subscription ends. The destination cache retains all items. - /// - /// - /// or is null. - /// - /// + /// The source of . + /// The destination. + /// A disposable which will unsubscribe from the source. + /// + /// source + /// or + /// destination. + /// public static IDisposable PopulateInto(this IObservable> source, ISourceCache destination) where TObject : notnull where TKey : notnull @@ -4226,10 +3584,17 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// The source changeset stream. - /// The destination intermediate cache to populate. - /// Overload that targets an . + /// + /// Populates a source into the specified cache. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The destination. + /// A disposable which will unsubscribe from the source. + /// source + /// or + /// destination. public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) where TObject : notnull where TKey : notnull @@ -4240,10 +3605,14 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// The source changeset stream. - /// The destination lock-free cache to populate. - /// Overload that targets a . + /// + /// Populates a source into the specified cache. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The destination. + /// A disposable which will unsubscribe from the source. public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) where TObject : notnull where TKey : notnull @@ -4255,30 +3624,19 @@ public static IDisposable PopulateInto(this IObservable - /// Projects the current cache state through after each modification. - /// Emits a new value of on every changeset. + /// The latest copy of the cache is exposed for querying after each modification to the underlying data. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source changeset stream. - /// Projects the current snapshot to a result value. - /// An observable that emits a projected value after each changeset. - /// - /// - /// EventBehavior - /// AddCache updated, then invoked and result emitted. - /// UpdateCache updated, then invoked and result emitted. - /// RemoveCache updated, then invoked and result emitted. - /// RefreshCache updated, then invoked and result emitted. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: The selector is called on every changeset, which can be chatty. The exposes the full cache state for LINQ-style queries. - /// - /// or is null. - /// - /// + /// The source of . + /// A result selector. + /// An observable which emits the destination values. + /// + /// source + /// or + /// resultSelector. + /// public static IObservable QueryWhenChanged(this IObservable> source, Func, TDestination> resultSelector) where TObject : notnull where TKey : notnull @@ -4294,7 +3652,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -4312,8 +3670,8 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// Should the query be triggered for observables on individual items. + /// The source of . + /// A Should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source, Func> itemChangedTrigger) @@ -4327,14 +3685,12 @@ public static IObservable> QueryWhenChanged - /// Cache-aware equivalent of Publish().RefCount(). An internal cache is created on the first subscriber - /// and disposed when the last subscriber unsubscribes. All subscribers share the same upstream subscription. + /// Cache equivalent to Publish().RefCount(). The source is cached so long as there is at least 1 subscriber. /// /// The type of the object. - /// The type of the key. - /// The source changeset stream. - /// A ref-counted observable changeset stream. - /// + /// The type of the destination key. + /// The source of . + /// An observable which emits change sets that are ref counted. public static IObservable> RefCount(this IObservable> source) where TObject : notnull where TKey : notnull @@ -4345,23 +3701,13 @@ public static IObservable> RefCount(thi } /// - /// Signals downstream operators to re-evaluate the specified item. Produces a changeset with a single Refresh change. + /// Signal observers to re-evaluate the specified item. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The item to refresh. - /// - /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. - /// - /// EventBehavior - /// RefreshProduced for the specified item. Downstream operators re-evaluate this item against their current logic (filter predicate, sort comparer, group key selector, etc.). - /// OtherNo Add, Update, or Remove events are produced by this method. - /// - /// - /// is null. - /// - /// + /// The source. + /// The item. + /// source. public static void Refresh(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -4372,13 +3718,13 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signals downstream operators to re-evaluate the specified items. Produces one changeset with a Refresh for each item. + /// Signal observers to re-evaluate the specified items. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The items to refresh. - /// is null. + /// The source. + /// An items. + /// source. public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -4389,12 +3735,12 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signals downstream operators to re-evaluate all items in the cache. Produces one changeset with a Refresh for every item. + /// Signal observers to re-evaluate the all items. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// is null. + /// The source. + /// source. public static void Refresh(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -4405,24 +3751,14 @@ public static void Refresh(this ISourceCache sourc } /// - /// Removes the specified item from the cache. Produces a Remove changeset if the item exists, nothing otherwise. + /// Removes the specified item from the cache. + /// If the item is not contained in the cache then the operation does nothing. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The item to remove. - /// - /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. - /// - /// EventBehavior - /// RemoveProduced if the key exists in the cache. The removed value is included in the changeset. - /// OtherNo Add, Update, or Refresh events are produced by this method. - /// - /// - /// is null. - /// - /// - /// + /// The source. + /// The item. + /// source. public static void Remove(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -4433,13 +3769,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the item with the specified key from the cache. Produces a Remove changeset if the key exists, nothing otherwise. + /// Removes the specified key from the cache. + /// If the item is not contained in the cache then the operation does nothing. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The key of the item to remove. - /// is null. + /// The source. + /// The key. + /// source. public static void Remove(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -4450,14 +3787,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified items from the cache. Any items not present in the cache are ignored. - /// Produces a Remove changeset for each item that existed. + /// Removes the specified items from the cache. + /// Any items not contained in the cache are ignored. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The items to remove. - /// is null. + /// The source. + /// An items. + /// source. public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -4468,14 +3805,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the items with the specified keys from the cache. Any keys not present are ignored. - /// Produces a Remove changeset for each key that existed. + /// Removes the specified keys from the cache. + /// Any keys not contained in the cache are ignored. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The keys to remove. - /// is null. + /// The source. + /// An keys. + /// source. public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -4485,10 +3822,15 @@ public static void Remove(this ISourceCache source source.Edit(updater => updater.Remove(keys)); } - /// - /// The intermediate cache. - /// The key of the item to remove. - /// Overload that targets an . + /// + /// Removes the specified key from the cache. + /// If the item is not contained in the cache then the operation does nothing. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// The key. + /// source. public static void Remove(this IIntermediateCache source, TKey key) where TObject : notnull where TKey : notnull @@ -4498,10 +3840,15 @@ public static void Remove(this IIntermediateCache source.Edit(updater => updater.Remove(key)); } - /// - /// The intermediate cache. - /// The keys to remove. - /// Overload that targets an . + /// + /// Removes the specified keys from the cache. + /// Any keys not contained in the cache are ignored. + /// + /// The type of the object. + /// The type of the key. + /// The source. + /// An keys. + /// source. public static void Remove(this IIntermediateCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -4512,14 +3859,15 @@ public static void Remove(this IIntermediateCache } /// - /// Strips the key from a cache changeset, converting to - /// (list changeset). All indexed changes are dropped (sorting is not supported). + /// Removes the key which enables all observable list features of dynamic data. /// - /// The type of the object. - /// The type of the key. - /// The source changeset stream. - /// A list changeset stream without key information. - /// + /// + /// All indexed changes are dropped i.e. sorting is not supported by this function. + /// + /// The type of object. + /// The type of key. + /// The source of . + /// An observable which emits change sets. public static IObservable> RemoveKey(this IObservable> source) where TObject : notnull where TKey : notnull @@ -4535,13 +3883,14 @@ public static IObservable> RemoveKey(this IOb } /// - /// Removes a specific key from the cache. Equivalent to source.Edit(u => u.RemoveKey(key)). + /// Removes the specified key from the cache. + /// If the item is not contained in the cache then the operation does nothing. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The key to remove. - /// is null. + /// The source. + /// The key. + /// source. public static void RemoveKey(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -4552,13 +3901,14 @@ public static void RemoveKey(this ISourceCache sou } /// - /// Removes multiple keys from the cache in a single Edit call. Keys not present in the cache are ignored. + /// Removes the specified keys from the cache. + /// Any keys not contained in the cache are ignored. /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The keys to remove. - /// is null. + /// The source. + /// An keys. + /// source. public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -4568,12 +3918,19 @@ public static void RemoveKeys(this ISourceCache so source.Edit(updater => updater.RemoveKeys(keys)); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the optional left and right values into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Joins the left and right observable data sources, taking all right values and combining any matching left values. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4590,48 +3947,18 @@ public static IObservable> RightJoin - /// Joins two changeset streams, producing a result for every right-side key. The left side is - /// because a matching left item may or may not exist. All right items - /// appear in the output regardless. Equivalent to SQL RIGHT OUTER JOIN. + /// Joins the left and right observable data sources, taking all right values and combining any matching left values. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). - /// An observable changeset keyed by . - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddAlways emits. Invokes with the matching left (or Optional.None) and the right value. - /// UpdateRe-invokes the selector with current left (if any) and the new right value. - /// RemoveRemoves the joined result. - /// RefreshForwarded as Refresh on the joined result. - /// - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddIf matching right items exist, re-invokes the selector (left transitions from None to Some) and emits Updates. - /// UpdateIf matching right items exist, re-invokes the selector with the new left value. - /// RemoveIf matching right items exist, re-invokes the selector (left transitions from Some to None) and emits Updates. - /// RefreshIf joined results exist, forwarded as Refresh. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4647,12 +3974,20 @@ public static IObservable> RightJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. - /// Overload that omits the key from the result selector. Delegates to . + /// + /// Groups the right data source and joins the two sources matching them using the specified key selector, , taking all right values and combining any matching left values. + /// This is the equivalent of SQL left join. + /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4669,49 +4004,19 @@ public static IObservable> RightJoinMany - /// Groups right-side items by their mapped key, then right-joins each group to the left source. - /// A result is produced for every key that has at least one right item. The left value is - /// because a matching left item may or may not exist. - /// Equivalent to SQL RIGHT OUTER JOIN with the right side grouped. + /// Groups the right data source and joins the two sources matching them using the specified key selector,, taking all right values and combining any matching left values. + /// This is the equivalent of SQL left join. /// - /// The item type of the left source. - /// The key type of the left source. - /// The item type of the right source. - /// The key type of the right source. - /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). - /// An observable changeset keyed by . - /// - /// - /// Right-side change handling: - /// - /// EventBehavior - /// AddUpdates the right group. If the group was previously empty, emits an Add with the current left (if any). Otherwise emits an Update. - /// UpdateUpdates the right group and re-invokes . - /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// - /// Left-side change handling: - /// - /// EventBehavior - /// AddIf a non-empty right group exists, re-invokes the selector (left transitions from None to Some) and emits an Update. - /// UpdateIf a non-empty right group exists, re-invokes the selector with the new left value. - /// RemoveIf a non-empty right group exists, re-invokes the selector (left transitions from Some to None) and emits an Update. - /// RefreshIf a joined result exists, forwarded as Refresh. - /// - /// - /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. - /// - /// Any argument is null. - /// - /// - /// - /// + /// The object type of the left data source. + /// The key type of the left data source. + /// The object type of the right data source. + /// The key type of the right data source. + /// The resulting object which. + /// The left of data source. + /// The right of data source. + /// A Specify the foreign key on the right data source. + /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). + /// An observable which will emit change sets. public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4728,16 +4033,13 @@ public static IObservable> RightJoinMany - /// Skips the initial snapshot changeset that Connect() typically emits, then forwards all subsequent changesets. - /// Internally uses DeferUntilLoaded().Skip(1). + /// Defer the subscription until loaded and skip initial change set. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// An observable that skips the first changeset and forwards all others. - /// is null. - /// - /// + /// The source of . + /// An observable which emits change sets. + /// source. public static IObservable> SkipInitial(this IObservable> source) where TObject : notnull where TKey : notnull @@ -4748,13 +4050,15 @@ public static IObservable> SkipInitial( } /// - /// Obsolete: use SortAndBind instead. Sorts using the specified comparer. + /// Sorts using the specified comparer. + /// Returns the underlying ChangeSet as per the system conventions. + /// The resulting change set also exposes a sorted key value collection of the underlying cached data. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer. - /// Sort optimisation flags. Specify one or more sort optimisations. + /// The source of . + /// An comparer. + /// The Sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). /// An observable which emits change sets. /// @@ -4774,13 +4078,13 @@ public static IObservable> Sort(t } /// - /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable. + /// Sorts a sequence as, using the comparer observable to determine order. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer observable. - /// The sort optimisations. + /// The source of . + /// An of which enables the sort order to be changed. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4795,14 +4099,14 @@ public static IObservable> Sort(t } /// - /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable with a manual re-sort signal. + /// Sorts a sequence as, using the comparer observable to determine order. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer observable. - /// Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// The source of . + /// An of which enables the sort order to be changed. + /// An of Signal to instruct the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4817,14 +4121,14 @@ public static IObservable> Sort(t } /// - /// Obsolete: use SortAndBind instead. Sorts using a static comparer with a manual re-sort signal. + /// Sorts a sequence as, using the comparer observable to determine order. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer to sort on. - /// Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// The source of . + /// An comparer to sort on. + /// An of Signal to instruct the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4839,18 +4143,16 @@ public static IObservable> Sort(t } /// - /// Sorts the changeset stream by the value returned from . Creates a comparer internally - /// and delegates to . - /// Since Sort is obsolete, prefer SortAndBind for new code. + /// Sorts a sequence by selected property. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// Expression that selects a comparable value from each item. - /// The sort direction. Defaults to ascending. - /// Sort optimization flags. - /// The number of updates before the entire list is re-sorted (rather than inline sort). - /// An observable that emits sorted changesets. + /// The source of . + /// A expression. + /// The sort order. Defaults to ascending. + /// The sort optimisations. + /// The reset threshold. + /// An observable which emits change sets. public static IObservable> SortBy( this IObservable> source, Func expression, @@ -4874,76 +4176,91 @@ public static IObservable> SortBy } /// - /// Prepends an empty changeset to the source stream, ensuring subscribers always receive an immediate - /// (empty) notification on subscription. Uses Rx's StartWith. + /// Prepends an empty change set to the source. /// - /// The type of the object. - /// The type of the key. - /// The source observable change set. - /// An observable that emits an empty changeset first, then all source changesets. + /// The object of the change set. + /// The key of the change set. + /// The source of . Observable change set. + /// An observable which emits change sets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); - /// - /// The source observable sorted change set. - /// An observable that emits an empty sorted changeset first, then all source changesets. - /// Overload for . + /// + /// Prepends an empty change set to the source. + /// + /// The object of the change set. + /// The key of the change set. + /// The source of . Observable change set. + /// An observable which emits sorted change sets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(SortedChangeSet.Empty); - /// - /// The source observable virtual change set. - /// An observable that emits an empty virtual changeset first, then all source changesets. - /// Overload for . + /// + /// Prepends an empty change set to the source. + /// + /// The object of the change set. + /// The key of the change set. + /// The source of . Observable change set. + /// An observable which emits virtual change sets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(VirtualChangeSet.Empty); - /// - /// The source observable paged change set. - /// An observable that emits an empty paged changeset first, then all source changesets. - /// Overload for . + /// + /// Prepends an empty change set to the source. + /// + /// The object of the change set. + /// The key of the change set. + /// The source of . Observable change set. + /// An observable which emits paged change sets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(PagedChangeSet.Empty); - /// - /// The type of the object. - /// The type of the key. - /// The grouping key type. - /// The source observable group change set. - /// An observable that emits an empty group changeset first, then all source changesets. - /// Overload for . - public static IObservable> StartWithEmpty(this IObservable> source) + /// + /// Prepends an empty change set to the source. + /// + /// The object of the change set. + /// The key of the change set. + /// The grouping key type. + /// An source observable change set. + /// An observable which emits group change sets. + public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(GroupChangeSet.Empty); - /// - /// The type of the object. - /// The type of the key. + /// + /// Prepends an empty change set to the source. + /// + /// The object of the change set. + /// The key of the change set. /// The grouping key type. - /// The source observable immutable group change set. - /// An observable that emits an empty immutable group changeset first, then all source changesets. - /// Overload for . + /// An source observable change set. + /// An observable which emits immutable group change sets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(ImmutableGroupChangeSet.Empty); - /// + /// + /// Prepends an empty change set to the source. + /// /// The type of the item. - /// The source read only collection observable. - /// An observable that emits an empty collection first, then all source collections. - /// Overload for . + /// An source read only collection. + /// A read only collection. public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); - /// - /// The source changeset stream. - /// The item to prepend. The key is extracted from . - /// Overload for items that implement . Delegates to the explicit key overload. + /// + /// The equivalent of rx StartsWith operator, but wraps the item in a change where reason is ChangeReason.Add. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The item. + /// An observable which emits change sets. public static IObservable> StartWithItem(this IObservable> source, TObject item) where TObject : IKey where TKey : notnull @@ -4954,15 +4271,14 @@ public static IObservable> StartWithItem - /// Prepends a changeset containing a single Add for the given item and key to the source stream. - /// The Rx equivalent of StartWith, but wrapped as a DynamicData changeset. + /// The equivalent of rx StartWith operator, but wraps the item in a change where reason is ChangeReason.Add. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The item to prepend. - /// The key for the item. - /// An observable that emits a single-item Add changeset first, then all source changesets. + /// The source of . + /// The item. + /// The key. + /// An observable which emits change sets. public static IObservable> StartWithItem(this IObservable> source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -4974,38 +4290,19 @@ public static IObservable> StartWithItem - /// Creates an subscription per item via . - /// Subscriptions are created on Add/Update and disposed on Update/Remove. All active subscriptions - /// are disposed when the stream completes, errors, or the subscription is disposed. + /// Subscribes to each item when it is added to the stream and un-subscribes when it is removed. All items will be unsubscribed when the stream is disposed. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// Factory that creates an for each item. Called on Add and Update (for the new value). - /// A stream that forwards all changesets from unchanged. + /// The source of . + /// A subscription function. + /// An observable which emits a change set. + /// source + /// or + /// subscriptionFactory. /// - /// - /// Change reason handling: - /// - /// EventBehavior - /// AddCalls , stores the returned . - /// UpdateDisposes the previous subscription, then calls for the new value. - /// RemoveDisposes the subscription for the removed item. - /// RefreshPassed through. No subscription change. - /// - /// - /// - /// Internally implemented using - /// and , so disposal semantics match . - /// - /// - /// Use this to tie per-item side effects (event subscriptions, polling timers, child observable subscriptions) - /// to the lifecycle of items in the cache. - /// + /// Subscribes to each item when it is added or updates and un-subscribes when it is removed. /// - /// or is null. - /// - /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -5016,10 +4313,20 @@ public static IObservable> SubscribeMany(source, subscriptionFactory).Run(); } - /// - /// The source changeset stream. - /// Factory that creates an for each item. Receives the item and its key. - /// Overload whose factory receives both the item and the key. See for full details. + /// + /// Subscribes to each item when it is added to the stream and unsubscribes when it is removed. All items will be unsubscribed when the stream is disposed. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// A subscription function. + /// An observable which emits a change set. + /// source + /// or + /// subscriptionFactory. + /// + /// Subscribes to each item when it is added or updates and unsubscribes when it is removed. + /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -5035,15 +4342,24 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// The source observable change set. + /// The source of . Observable change set. /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull where TKey : notnull => source.WhereReasonsAreNot(ChangeReason.Refresh); - /// - /// An observable that emits instances. - /// Overload that accepts observable caches. Internally calls Connect() on each cache and delegates to the changeset overload. + /// + /// Transforms an observable sequence of observable caches into a single sequence + /// producing values only from the most recent observable sequence. + /// Each time a new inner observable sequence is received, unsubscribe from the + /// previous inner observable sequence and clear the existing result set. + /// + /// The type of the object. + /// The type of the key. + /// An source. + /// + /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. + /// public static IObservable> Switch(this IObservable> sources) where TObject : notnull where TKey : notnull @@ -5054,26 +4370,17 @@ public static IObservable> Switch(this } /// - /// Subscribes to the latest inner changeset stream, unsubscribing from the previous one on each switch. - /// When switching, the old source's items are removed and the new source's items are added. + /// Transforms an observable sequence of observable changes sets into an observable sequence + /// producing values only from the most recent observable sequence. + /// Each time a new inner observable sequence is received, unsubscribe from the + /// previous inner observable sequence and clear the existing result set. /// /// The type of the object. /// The type of the key. - /// An observable that emits inner changeset streams. - /// A changeset stream reflecting the items from the most recently emitted inner source. - /// - /// - /// EventBehavior - /// AddForwarded from the active inner source. - /// UpdateForwarded from the active inner source. - /// RemoveForwarded from the active inner source. - /// RefreshForwarded from the active inner source. - /// OnErrorAn error from any inner source or the outer source terminates the stream. - /// OnCompletedCompletes when the outer source and the current inner source have both completed. - /// - /// On switch: Remove is emitted for all items from the previous source, then Add for all items from the new source. - /// Worth noting: Each switch clears the entire downstream cache before populating from the new source. Subscribers see a full remove-then-add reset on every switch. - /// + /// An of of streams. source. + /// + /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. + /// public static IObservable> Switch(this IObservable>> sources) where TObject : notnull where TKey : notnull @@ -5088,26 +4395,27 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull where TKey : notnull => source.QueryWhenChanged(query => new ReadOnlyCollectionLight(query.Items)); /// - /// Bridges a standard Rx observable of individual items into a DynamicData changeset stream. - /// Each emission becomes an Add (or Update if the key already exists). - /// Supports optional per-item expiration and size limiting. + /// Converts the observable to an observable change set. + /// Change set observes observable change events. /// /// The type of the object. /// The type of the key. - /// The source observable of individual items. - /// Selects the unique key for each item. - /// Optional: per-item expiration time. Return null for no expiration. - /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// Optional scheduler for expiration timing. - /// An observable changeset stream. - /// or is null. + /// An source. + /// A key selector. + /// A Specify on a per object level the maximum time before an object expires from a cache. + /// Remove the oldest items when the size has reached this limit. + /// The scheduler (only used for time expiry). + /// An observable which will emit changes. + /// source + /// or + /// keySelector. public static IObservable> ToObservableChangeSet( this IObservable source, Func keySelector, @@ -5129,19 +4437,20 @@ public static IObservable> ToObservableChangeSet - /// Bridges a standard Rx observable of item batches into a DynamicData changeset stream. - /// Each batch is processed with AddOrUpdate, producing Add or Update changes per item. - /// Supports optional per-item expiration and size limiting. + /// Converts the observable to an observable change set. + /// Change set observes observable change events. /// /// The type of the object. /// The type of the key. - /// The source observable of item batches. - /// Selects the unique key for each item. - /// Optional: per-item expiration time. Return null for no expiration. - /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// Optional scheduler for expiration timing. - /// An observable changeset stream. - /// or is null. + /// An of source. + /// A key selector. + /// A Specify on a per object level the maximum time before an object expires from a cache. + /// Remove the oldest items when the size has reached this limit. + /// The scheduler (only used for time expiry). + /// An observable change set. + /// source + /// or + /// keySelector. public static IObservable> ToObservableChangeSet( this IObservable> source, Func keySelector, @@ -5163,34 +4472,15 @@ public static IObservable> ToObservableChangeSet - /// Watches a single key in the source changeset stream, emitting Optional.Some(value) when the key - /// is present and Optional.None when it is removed. Duplicate values are suppressed via . + /// Converts an observable change set into an observable optional that emits the value for the given key. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The key to watch. - /// Optional comparer to suppress duplicate emissions. Uses default equality if null. - /// An observable of that reflects the presence or absence of the specified key. - /// - /// - /// Unlike , this emits None on removal - /// (rather than the removed value), making it possible to distinguish "key is absent" from "key has a value". - /// - /// - /// EventBehavior - /// AddEmits Optional.Some(value) if the key was not previously tracked. - /// UpdateEmits Optional.Some(newValue) if the new value differs from the previous per . Otherwise suppressed. - /// RemoveEmits Optional.None. - /// RefreshEmits Optional.Some(value) if the value differs from the last emission per . Otherwise suppressed. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No emission occurs if the key is not present at subscription time. To get an initial None when the key is absent, use the overload with initialOptionalWhenMissing: true. - /// - /// is null. - /// - /// + /// The source of . + /// The key value. + /// Optional instance used to determine if an object value has changed. + /// An observable optional. + /// source is null. public static IObservable> ToObservableOptional(this IObservable> source, TKey key, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -5205,15 +4495,12 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// The key value. /// Indicates if an initial Optional None should be emitted if the value doesn't exist. /// Optional instance used to determine if an object value has changed. /// An observable optional. /// source is null. - /// - /// Worth noting: Uses lock-based coordination. If the key exists synchronously on Connect(), the initial None may or may not be emitted depending on timing. - /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, bool initialOptionalWhenMissing, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -5238,9 +4525,9 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// The source changeset stream. - /// The sort function. - /// The sort order. Defaults to ascending. + /// The source of . + /// A sort function. + /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, Func sort, SortDirection sortOrder = SortDirection.Ascending) where TObject : notnull @@ -5252,8 +4539,8 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The sort comparer. + /// The source of . + /// An sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) where TObject : notnull @@ -5265,8 +4552,21 @@ public static IObservable> ToSortedCollection(items); }); - /// - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// Should a new transform be applied when a refresh event is received. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5278,8 +4578,21 @@ public static IObservable> Transform transformFactory(current), transformOnRefresh); } - /// - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// Should a new transform be applied when a refresh event is received. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5291,8 +4604,21 @@ public static IObservable> Transform transformFactory(current, key), transformOnRefresh); } - /// - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// Should a new transform be applied when a refresh event is received. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5304,8 +4630,21 @@ public static IObservable> Transform(source, transformFactory, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// This overload accepts an optional forceTransform predicate filtering by source item only (without the key). The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5317,8 +4656,21 @@ public static IObservable> Transform transformFactory(current), forceTransform?.ForForced()); } - /// - /// This overload accepts an optional forceTransform predicate filtering by source item and key. The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5331,43 +4683,20 @@ public static IObservable> Transform - /// Projects each item in the changeset to a new form using a synchronous transform factory. + /// Projects each update item to a new form using the specified transform function. /// - /// The type of the transformed items. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// A function that produces a from the current source item, the previous source item (if any), and the key. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. - /// An observable changeset of transformed items. - /// - /// - /// Transform maintains a 1:1 mapping between source and destination items, keyed identically. The factory - /// is called once per Add and once per Update. Removes are forwarded without calling the factory. - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddCalls factory, emits Add. - /// UpdateCalls factory (receives current item, previous item, key), emits Update with Previous preserved. - /// RemoveEmits Remove. Factory is NOT called. - /// RefreshForwarded as Refresh without re-transforming. To re-transform on Refresh, use the parameter or the transformOnRefresh overloads. - /// - /// Worth noting: By default, Refresh does NOT re-invoke the transform factory (it is just forwarded). Set transformOnRefresh: true to re-transform on Refresh. - /// - /// When emits a predicate, every cached item is tested against it. - /// Matching items are re-transformed and emitted as Updates. - /// - /// - /// Factory exceptions propagate as , terminating the stream. - /// Use - /// to catch factory errors without killing the stream. - /// - /// - /// - /// - /// - /// or is null. + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5383,15 +4712,41 @@ public static IObservable> Transform(source, transformFactory).Run(); } - /// - /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of Invoke to force a new transform for all items. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.Transform((cur, _, _) => transformFactory(cur), forceTransform.ForForced()); - /// - /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of Invoke to force a new transform for all items.# + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5404,8 +4759,21 @@ public static IObservable> Transform transformFactory(cur, key), forceTransform.ForForced()); } - /// - /// This overload accepts of to force re-transformation of ALL items when the observable emits. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of Invoke to force a new transform for all items.# + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5418,8 +4786,21 @@ public static IObservable> Transform()); } - /// - /// This overload takes a simpler factory that receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -5432,8 +4813,21 @@ public static IObservable> TransformAsync transformFactory(current), forceTransform); } - /// - /// This overload takes a factory that receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -5447,38 +4841,20 @@ public static IObservable> TransformAsync - /// Async version of . - /// Projects each item using an async factory that returns . + /// Projects each update item to a new form using the specified transform function. /// - /// The type of the transformed items. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// An async function that produces a from the current source item, the previous source item (if any), and the key. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. - /// An observable changeset of transformed items. - /// - /// - /// Transforms within a single changeset batch execute concurrently. The entire batch must complete - /// before the resulting changeset is emitted. Use the overloads - /// to control maximum concurrency and Refresh handling. - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddAwaits factory, emits Add. - /// UpdateAwaits factory (receives current, previous, key), emits Update. - /// RemoveEmits Remove. Factory is NOT called. - /// RefreshForwarded as Refresh by default. Use to re-transform. - /// - /// Worth noting: Transforms are batched per changeset (all tasks must complete before the next changeset is processed). Completion waits for in-flight transforms. Remove does NOT cancel in-flight transforms for the removed key. - /// - /// Factory exceptions propagate as . Use - /// - /// to catch factory errors without terminating the stream. - /// - /// - /// or is null. + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -5491,8 +4867,21 @@ public static IObservable> TransformAsync(source, transformFactory, null, forceTransform).Run(); } - /// - /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// The transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -5505,8 +4894,21 @@ public static IObservable> TransformAsync transformFactory(current), options); } - /// - /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// The transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -5519,8 +4921,21 @@ public static IObservable> TransformAsync transformFactory(current, key), options); } - /// - /// This overload accepts to control concurrency and Refresh handling. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// The transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -5534,31 +4949,26 @@ public static IObservable> TransformAsync - /// Optimized transform for immutable items with deterministic (pure) transform functions. - /// Refresh changes are dropped entirely since immutable items cannot change in place. + /// Projects each update item to a new form using the specified transform function, with optimizations for stateless/deterministic transformation of immutable items. /// - /// The type of the transformed items. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// A pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. - /// An observable changeset of transformed items. + /// The type of collection items produced by the transformation. + /// The type of collection items to be transformed. + /// The type of the key values of each collection item. + /// The source of . Stream of collection items to be transformed. + /// A transformation to be applied to each item. + /// A stream of collection changesets where upstream collection items are transformed by the given factory function. /// - /// - /// Because the transform is assumed to be stateless and deterministic, this operator does not track - /// previously transformed items. This reduces memory overhead compared to . - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddCalls factory, emits Add. - /// UpdateCalls factory, emits Update. - /// RemoveEmits Remove. Factory is NOT called. - /// RefreshDROPPED. Immutable items do not change, so Refresh is meaningless. + /// The goal of this operator is to optimize a common use-case of reactive programming, where data values flowing through a stream are immutable, and state changes are distributed by publishing new immutable items as replacements, instead of mutating the items directly. + /// In addition to assuming that all collection items are immutable, this operator also assumes that the given transformation function is deterministic, such that the result it returns will always be equivalent each time a specific input is passed to it. In other words, the transformation itself also contains no mutable state. + /// Under these assumptions, this operator can bypass the need to keep track of every collection item that passes through it, which the normal operator must do, in order to re-evaluate transformations during a refresh operation. + /// Consider using this operator when the following are true: + /// + /// Your collection items are immutable, and changes are published by replacing entire items + /// Your transformation logic does not change over the lifetime of the stream, only the items do + /// Your transformation function runs quickly, and does not heavily allocate memory /// - /// Use this when items are immutable, the factory is pure, and the factory is cheap. If any of these conditions are false, use instead. + /// Note that, because transformation is purely deterministic, Refresh operations are transparently ignored by this operator. /// - /// or is null. public static IObservable> TransformImmutable( this IObservable> source, Func transformFactory) @@ -5576,55 +4986,67 @@ public static IObservable> TransformImmutable - /// Flattens each source item into zero or more destination items (1:N), producing a single flat changeset. - /// Each child item must have a globally unique key across all parents. + /// Equivalent to a select many transform. To work, the key must individually identify each child. /// - /// The type of the child items. - /// The type of the child item keys. - /// The type of the source (parent) items. - /// The type of the source (parent) keys. - /// The source changeset of parent items. - /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. - /// Extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. - /// An observable changeset of flattened child items. - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddCalls , emits Add for each child. - /// UpdateDiffs old children vs new children: emits Remove for removed children, Add for new children, Update for children with matching keys. - /// RemoveEmits Remove for all children of the removed parent. - /// RefreshPropagated as Refresh to all children (no re-expansion). - /// - /// Worth noting: If two source items produce children with the same key, last-in-wins. Refresh does NOT re-expand children (only Update does). - /// If two parents produce children with the same key, last-in-wins. Use the async variant with a to control conflict resolution. - /// - /// , , or is null. - /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// A Will select a enumerable of values. + /// A key selector which must be unique across all. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// This overload accepts an selector. Changes to the child collection (adds, removes, replacements) are automatically observed and reflected downstream. + /// + /// Flatten the nested observable collection, and subsequently observe observable collection changes. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// A Will select a enumerable of values. + /// A key selector which must be unique across all. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// This overload accepts a selector. Changes to the child collection are automatically observed and reflected downstream. + /// + /// Flatten the nested observable collection, and subsequently observe observable collection changes. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// A Will select a enumerable of values. + /// A key selector which must be unique across all. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// This overload accepts an selector. The child cache is live: subsequent changes to it are automatically propagated downstream. + /// + /// Flatten the nested observable cache, and subsequently observe observable cache changes. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// A Will select an observable cache of values. + /// A key selector which must be unique across all. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull @@ -5632,31 +5054,19 @@ public static IObservable> TransformMa where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); /// - /// Async version of . - /// Flattens each source item into zero or more destination items using an async factory. + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. /// - /// The type of the child items. - /// The type of the child item keys. - /// The type of the source (parent) items. - /// The type of the source (parent) keys. - /// The source changeset of parent items. - /// An async function that expands a parent item (and its key) into an of children. - /// Extracts a unique key from each child item. - /// Optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. - /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. - /// An observable changeset of flattened child items. - /// - /// - /// Because each parent's expansion is async, child collections may arrive via separate changesets - /// (unlike the synchronous TransformMany which batches all children into one changeset). - /// - /// - /// Factory exceptions propagate as . Use - /// - /// to catch errors without killing the stream. - /// - /// - /// or is null. + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable changeset with the transformed values. + /// The source of . + /// Async function to transform a and into an of . + /// A key selector which must be unique across all. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5670,8 +5080,20 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// This overload takes a factory that receives only the source item (without the key). + /// + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable changeset with the transformed values. + /// The source of . + /// Async function to transform a into an of . + /// A key selector which must be unique across all. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5680,8 +5102,21 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. + /// + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// The type of an observable collection of . + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a and into an of . + /// A key selector which must be unique across all. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5696,8 +5131,21 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. + /// + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// The type of an observable collection of . + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a into an of . + /// A key selector which must be unique across all. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5707,8 +5155,19 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// This overload returns an per parent. The child cache is live: its changes propagate downstream. No keySelector is needed since the cache already has keys. The factory receives the source item and its key. + /// + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a and into an of . + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5722,8 +5181,19 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer).Run(); } - /// - /// This overload returns an per parent. The child cache is live. The factory receives only the source item. + /// + /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a and into an of . + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5733,23 +5203,20 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), equalityComparer, comparer); /// - /// Async version of - /// with error handling. Factory exceptions are caught and routed to instead of - /// terminating the stream. - /// - /// The type of the child items. - /// The type of the child item keys. - /// The type of the source (parent) items. - /// The type of the source (parent) keys. - /// The source changeset of parent items. - /// An async function that expands a parent item (and its key) into an of children. - /// Extracts a unique key from each child item. - /// Called when throws. The faulting item is skipped and the stream continues. - /// Optional comparer to determine if two child items with the same key are equal. - /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. - /// An observable changeset of flattened child items. - /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. - /// , , or is null. + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable changeset with the transformed values. + /// The source of . + /// Async function to transform a and into an of . + /// A key selector which must be unique across all. + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5764,8 +5231,21 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// This overload takes a factory that receives only the source item (without the key). + /// + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable changeset with the transformed values. + /// The source of . + /// Async function to transform a into an of . + /// A key selector which must be unique across all. + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5774,8 +5254,22 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. + /// + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// The type of an observable collection of . + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a and into an of . + /// A key selector which must be unique across all. + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5791,8 +5285,22 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. + /// + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// The type of an observable collection of . + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a into an of . + /// A key selector which must be unique across all. + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5802,8 +5310,20 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// This overload returns an per parent. The child cache is live. The factory receives the source item and its key. + /// + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a and into an of . + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5818,8 +5338,20 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// This overload returns an per parent. The child cache is live. The factory receives only the source item. + /// + /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. + /// + /// The type of the destination. + /// The type of the destination key. + /// The type of the source. + /// The type of the source key. + /// An observable with the transformed change set. + /// The source of . + /// Async function to transform a into an of . + /// An Callback function for handling an errors. + /// Optional instance to determine if two elements are the same. + /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. + /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5829,48 +5361,19 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), errorHandler, equalityComparer, comparer); /// - /// Projects each item into a per-item observable. The latest value emitted by each item's observable - /// becomes the transformed value in the output changeset. + /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. /// - /// The type of the source items. + /// The type of the source changeset. /// The type of the key. - /// The type of the transformed items. - /// The source changeset observable. - /// A function that, given a source item and its key, returns an whose emissions become the transformed values. - /// An observable changeset where each key's value is the latest emission from its per-item observable. - /// - /// - /// Source changeset handling (parent events): - /// - /// - /// EventBehavior - /// AddCalls and subscribes to the returned observable. The item is not visible downstream until the observable emits its first value. - /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. The item disappears from downstream until the new observable emits. - /// RemoveDisposes the item's observable subscription. If the item was visible downstream, a Remove is emitted. - /// RefreshForwarded as Refresh if the item is currently visible downstream. Otherwise dropped. - /// - /// - /// Per-item observable handling (transform observable events): - /// - /// - /// EmissionBehavior - /// First valueThe transformed item appears downstream as an Add. - /// Subsequent valuesEach new value replaces the previous one: an Update is emitted downstream. - /// ErrorTerminates the entire output stream. - /// CompletedThe item remains at its last emitted value. No further updates are possible for this item. - /// - /// - /// Worth noting: Items are invisible downstream until their per-item observable emits at least one value. - /// If an item's observable never emits, that item never appears in the output. The transform factory's selector - /// runs under an internal lock, so it must not synchronously access other DynamicData caches (deadlock risk in - /// cross-cache pipelines). The output completes when the source completes and all per-item observables have - /// also completed. - /// - /// - /// or is null. - /// - /// - /// + /// The type of the destination changeset. + /// The source of . Changeset observable. + /// A Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. + /// + /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5882,8 +5385,18 @@ public static IObservable> TransformOnObservable< return new TransformOnObservable(source, transformFactory).Run(); } - /// - /// This overload takes a factory that receives only the source item (without the key). + /// + /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. + /// + /// The type of the source changeset. + /// The type of the key. + /// The type of the destination changeset. + /// The source of . Changeset observable. + /// A Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. + /// + /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. + /// + /// source or transformFactory. public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5894,8 +5407,23 @@ public static IObservable> TransformOnObservable< return source.TransformOnObservable((obj, _) => transformFactory(obj)); } - /// - /// This overload accepts a simpler factory that receives only the current item, and a forceTransform predicate filtering by source item only. + /// + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5908,8 +5436,23 @@ public static IObservable> TransformSafe transformFactory(current), errorHandler, forceTransform.ForForced()); } - /// - /// This overload accepts a factory that receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5923,26 +5466,22 @@ public static IObservable> TransformSafe - /// Projects each item using a synchronous factory, catching factory exceptions via a mandatory error handler - /// instead of terminating the stream. + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. /// - /// The type of the transformed items. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// A function that produces a from the current source item, the previous source item (if any), and the key. - /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. - /// An observable changeset of transformed items. - /// - /// - /// Behaves identically to - /// except that factory exceptions are routed to instead of propagating as . - /// Source-level errors (i.e. the source observable itself erroring) still propagate normally. - /// - /// Worth noting: Factory exceptions are caught per-item; the faulting item is skipped and reported to the error handler while the stream continues. Source-level errors still terminate the stream. - /// - /// , , or is null. + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5959,15 +5498,45 @@ public static IObservable> TransformSafe(source, transformFactory, errorHandler).Run(); } - /// - /// This overload accepts of to force re-transformation of ALL items. The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of Invoke to force a new transform for all items. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.TransformSafe((cur, _, _) => transformFactory(cur), errorHandler, forceTransform.ForForced()); - /// - /// This overload accepts of to force re-transformation of ALL items. The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of Invoke to force a new transform for all items.# + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5980,8 +5549,23 @@ public static IObservable> TransformSafe transformFactory(cur, key), errorHandler, forceTransform.ForForced()); } - /// - /// This overload accepts of to force re-transformation of ALL items. + /// + /// Projects each update item to a new form using the specified transform function, + /// providing an error handling action to safely handle transform errors without killing the stream. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Provides the option to safely handle errors without killing the stream. + /// An of Invoke to force a new transform for all items.# + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5994,8 +5578,22 @@ public static IObservable> TransformSafe()); } - /// - /// This overload takes a factory that receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -6009,8 +5607,22 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, forceTransform); } - /// - /// This overload takes a factory that receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -6025,19 +5637,21 @@ public static IObservable> TransformSafeAsync - /// Async version of . - /// Projects each item using an async factory, catching factory exceptions via a mandatory error handler. + /// Projects each update item to a new form using the specified transform function. /// - /// The type of the transformed items. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// An async function that produces a . - /// Called when throws or faults. The item is skipped and the stream continues. - /// Optional observable to force re-transformation of matching items. - /// An observable changeset of transformed items. - /// Combines the async execution model of with the error-safe behavior of . - /// , , or is null. + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// An of . Invoke to force a new transform for items matching the selected objects. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -6051,8 +5665,22 @@ public static IObservable> TransformSafeAsync(source, transformFactory, errorHandler, forceTransform).Run(); } - /// - /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// The Additional transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -6066,8 +5694,22 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, options); } - /// - /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// The Additional transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -6081,8 +5723,22 @@ public static IObservable> TransformSafeAsync transformFactory(current, key), errorHandler, options); } - /// - /// This overload accepts to control concurrency and Refresh handling. + /// + /// Projects each update item to a new form using the specified transform function. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An error handler. + /// The Additional transform options. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -6097,27 +5753,14 @@ public static IObservable> TransformSafeAsync - /// Builds a hierarchical tree from a flat changeset using a parent key selector. - /// Each item becomes a with Parent, Children, Depth, and IsRoot properties. + /// Transforms the object to a fully recursive tree, create a hierarchy based on the pivot function. /// - /// The type of the source items. Must be a reference type. + /// The type of the object. /// The type of the key. - /// The source changeset of flat items. - /// A function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. - /// Optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. - /// An observable changeset of items representing the tree. - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddCreates node, attaches to parent (or root if parent not found), emits Add. - /// UpdateUpdates node. If returns a different parent key, the node is re-parented. - /// RemoveRemoves node. Orphaned children become root nodes. - /// RefreshRe-evaluates parent key. May re-parent the node if the parent changed. - /// - /// Circular references are NOT detected. If item A is the parent of B and B is the parent of A, behavior is undefined. - /// - /// or is null. + /// The source of . + /// A pivot on. + /// An of . Observable to change the underlying predicate. + /// An observable which will emit change sets. public static IObservable, TKey>> TransformToTree(this IObservable> source, Func pivotOn, IObservable, bool>>? predicateChanged = null) where TObject : class where TKey : notnull @@ -6128,8 +5771,21 @@ public static IObservable, TKey>> TransformToTree return new TreeBuilder(source, pivotOn, predicateChanged).Run(); } - /// - /// This overload defaults to transformOnRefresh: false and does not provide an error handler (factory exceptions propagate as OnError). + /// + /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction) where TDestination : class where TSource : notnull @@ -6142,8 +5798,22 @@ public static IObservable> TransformWithInlineUpd return source.TransformWithInlineUpdate(transformFactory, updateAction, false); } - /// - /// This overload does not provide an error handler (factory exceptions propagate as OnError). The transformOnRefresh parameter controls Refresh behavior. + /// + /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. + /// Should a new transform be applied when a refresh event is received. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -6156,8 +5826,22 @@ public static IObservable> TransformWithInlineUpd return new TransformWithInlineUpdate(source, transformFactory, updateAction, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// This overload defaults to transformOnRefresh: false but includes an error handler for factory/update action exceptions. + /// + /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. + /// + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. + /// An error handler. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler) where TDestination : class where TSource : notnull @@ -6172,33 +5856,22 @@ public static IObservable> TransformWithInlineUpd } /// - /// Projects each item using a transform factory for Add, and mutates the existing transformed - /// item in place (via an update action) for Update, preserving the original object reference. + /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. /// - /// The type of the transformed items. Must be a reference type since items are mutated in place. - /// The type of the source items. - /// The type of the key. - /// The source changeset observable. - /// Called on Add (and optionally Refresh) to create a new . - /// Called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. - /// Called when or throws. The faulting item is skipped. - /// When true, Refresh changes call on the existing item. - /// An observable changeset of transformed items. - /// - /// - /// This is useful when the destination type is a ViewModel that should maintain its identity across updates. - /// Instead of replacing the entire ViewModel, the update action patches the existing instance. - /// - /// Change reason handling: - /// - /// Input reasonOutput behavior - /// AddCalls , emits Add. - /// UpdateCalls on the EXISTING transformed item (same reference), emits Update. - /// RemoveEmits Remove. - /// RefreshIf is true, calls . Otherwise forwarded as Refresh. - /// - /// - /// , , , or is null. + /// The type of the destination. + /// The type of the source. + /// The type of the key. + /// The source of . + /// A transform factory. + /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. + /// An error handler. + /// Should a new transform be applied when a refresh event is received. + /// + /// A transformed update collection. + /// + /// source + /// or + /// transformFactory. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -6217,7 +5890,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -6246,30 +5919,23 @@ static IEnumerable> ReplaceMoves(IChangeSet } /// - /// Emits true when all items in the cache satisfy a condition based on their per-item observable, - /// and false otherwise. Re-evaluates whenever the cache changes or any per-item observable emits. + /// + /// Produces a boolean observable indicating whether the latest resulting value from all of the specified observables matches + /// the equality condition. The observable is re-evaluated whenever. + /// + /// + /// i) The cache changes + /// or ii) The inner observable changes. + /// /// /// The type of the object. /// The type of the key. - /// The type of the value emitted by each per-item observable. - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each per-item observable's latest value. - /// An observable of bool that emits whenever the all-items condition changes. - /// , , or is null. - /// - /// - /// EventBehavior - /// AddA new per-item subscription is created. The aggregate condition is recalculated. - /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. - /// RemovePer-item subscription disposed. Condition recalculated over remaining items. - /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. - /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. - /// OnCompletedCompletes when the source and all per-item observables have completed. - /// - /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache is vacuously true. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. - /// - /// + /// The type of the value. + /// The source of . + /// A Selector which returns the target observable. + /// A equality condition. + /// An observable which boolean values indicating if true. + /// source. public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -6288,9 +5954,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// Selector which returns the target observable. - /// The equality condition. + /// The source of . + /// A Selector which returns the target observable. + /// A equality condition. /// An observable which boolean values indicating if true. /// source. public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -6299,40 +5965,50 @@ public static IObservable TrueForAll(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.All(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// Emits true when any item in the cache satisfies a condition based on its per-item observable, - /// and false when none do. Re-evaluates whenever the cache changes or any per-item observable emits. + /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches + /// the equality condition. The observable is re-evaluated whenever + /// i) The cache changes. + /// or ii) The inner observable changes. /// /// The type of the object. /// The type of the key. - /// The type of the value emitted by each per-item observable. - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each item and its per-item observable's latest value. - /// An observable of bool that emits whenever the any-item condition changes. - /// , , or is null. - /// - /// - /// EventBehavior - /// AddA new per-item subscription is created. The aggregate condition is recalculated. - /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. - /// RemovePer-item subscription disposed. Condition recalculated over remaining items. - /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. - /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. - /// OnCompletedCompletes when the source and all per-item observables have completed. - /// - /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache yields false. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. - /// - /// + /// The type of the value. + /// The source of . + /// A observable selector. + /// A equality condition. + /// An observable which boolean values indicating if true. + /// + /// source + /// or + /// observableSelector + /// or + /// equalityCondition. + /// public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); - /// - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each per-item observable's latest value (without the item). - /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. + /// + /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches + /// the equality condition. The observable is re-evaluated whenever + /// i) The cache changes. + /// or ii) The inner observable changes. + /// + /// The type of the object. + /// The type of the key. + /// The type of the value. + /// The source of . + /// A observable selector. + /// A equality condition. + /// An observable which boolean values indicating if true. + /// + /// source + /// or + /// observableSelector + /// or + /// equalityCondition. + /// public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -6346,36 +6022,24 @@ public static IObservable TrueForAny(this IObservab } /// - /// Sets the Index property on each item (which must implement ) - /// to reflect its position in the sorted output. Operates on . + /// Updates the index for an object which implements IIndexAware. /// /// The type of the object. /// The type of the key. - /// The source sorted changeset stream. - /// An observable that emits the sorted changesets after updating item indices. + /// The source of . + /// An observable which emits the sorted change set. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware where TKey : notnull => source.Do(changes => changes.SortedItems.Select((update, index) => new { update, index }).ForEach(u => u.update.Value.Index = u.index)); /// - /// Filters the source changeset stream to a single key, emitting each for that key. - /// Changes for all other keys are ignored. + /// Returns an observable of any updates which match the specified key, proceeded with the initial cache state. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The key to observe. - /// An observable of for the specified key only. - /// - /// - /// Emits Add, Update, Remove, and Refresh changes as they occur for the target key. - /// No initial emission occurs if the key is not yet present in the cache. This operator does not - /// produce changesets; it produces individual change notifications. For Optional-based watching, - /// use . - /// - /// - /// - /// + /// The source of . + /// The key. + /// An observable which emits the change. public static IObservable> Watch(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6386,33 +6050,14 @@ public static IObservable> Watch(this IObse } /// - /// Filters the source changeset stream to a single key, emitting the current value each time it changes. - /// Even emits the value on removal (the removed item's value). + /// Watches updates for a single value matching the specified key. /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The key to observe. - /// An observable of the item's value whenever it changes for the specified key. - /// - /// - /// Unlike , - /// this does not emit Optional.None on removal. It emits the removed item's value instead. - /// If you need to distinguish presence from absence, use ToObservableOptional. - /// - /// - /// EventBehavior - /// AddEmits the added item's value. - /// UpdateEmits the new value. - /// RemoveEmits the removed item's value (not None; use if you need removal detection). - /// RefreshEmits the current value. - /// OnErrorForwarded to the downstream observer. - /// OnCompletedForwarded to the downstream observer. - /// - /// Worth noting: No emission occurs if the key is not present at subscription time. Changes to other keys are ignored entirely. - /// - /// - /// + /// The source. + /// The key. + /// An observable which emits the object value. + /// source. public static IObservable WatchValue(this IObservableCache source, TKey key) where TObject : notnull where TKey : notnull @@ -6422,10 +6067,15 @@ public static IObservable WatchValue(this IObservableCac return source.Watch(key).Select(u => u.Current); } - /// - /// The source changeset stream. - /// The key to observe. - /// This overload extends IObservable<> instead of . + /// + /// Watches updates for a single value matching the specified key. + /// + /// The type of the object. + /// The type of the key. + /// The source of . + /// The key. + /// An observable which emits the object value. + /// source. public static IObservable WatchValue(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6436,34 +6086,13 @@ public static IObservable WatchValue(this IObservable - /// Emits an item whenever any of its properties change via . - /// Subscribes to PropertyChanged on each cache item using MergeMany. + /// Watches each item in the collection and notifies when any of them has changed. /// - /// The type of the object (must implement ). + /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// Specific property names to monitor. If empty, all property changes trigger emissions. - /// An observable that emits the item itself each time a monitored property changes. - /// - /// - /// Subscriptions are managed per item: created on Add, replaced on Update, disposed on Remove. - /// Errors from individual property subscriptions are silently ignored. The output is not a changeset - /// stream; it is a plain IObservable<TObject?>. If the same item changes multiple properties - /// rapidly, each change emits the item separately (no deduplication). - /// - /// - /// EventBehavior - /// AddSubscribes to PropertyChanged on the new item. - /// UpdateDisposes the old item's subscription and subscribes to the new item. - /// RemoveDisposes the item's PropertyChanged subscription. - /// RefreshNo effect on subscriptions. - /// OnErrorErrors from individual property subscriptions are silently ignored. Source errors terminate the stream. - /// OnCompletedCompletes when the source changeset stream completes. - /// - /// - /// - /// - /// + /// The source of . + /// specify properties to Monitor, or omit to monitor all property changes. + /// An observable which emits the object which has had a property changed. public static IObservable WhenAnyPropertyChanged(this IObservable> source, params string[] propertiesToMonitor) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6474,32 +6103,15 @@ public static IObservable WatchValue(this IObservable - /// Emits a (item + property value) whenever the specified property - /// changes on any item in the cache. Subscribes via using MergeMany. + /// Watches each item in the collection and notifies when any of them has changed. /// - /// The type of the object (must implement ). + /// The type of the object. /// The type of the key. - /// The type of the monitored property. - /// The source changeset stream. - /// Expression selecting the property to monitor. - /// When true (the default), the current property value is emitted immediately for each item upon subscription. - /// An observable of containing both the item and its property value. - /// - /// - /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual - /// property subscriptions are silently ignored. The output is not a changeset stream. If you only need - /// the value (not the owning item), use instead. - /// - /// - /// EventBehavior - /// AddSubscribes to the specified property on the new item. If notifyOnInitialValue is true, the current value is emitted immediately. - /// UpdateDisposes the old item's property subscription and subscribes to the new item. - /// RemoveDisposes the item's property subscription. No further emissions for this item. - /// RefreshNo effect on subscriptions. The existing property subscription continues. - /// OnErrorPer-item property subscription errors are silently ignored. Source errors terminate the stream. - /// OnCompletedCompletes when the source changeset stream completes. - /// - /// + /// The type of the value. + /// The source of . + /// An property accessor. + /// If true the resulting observable includes the initial value. + /// An observable which emits a property when it has changed. public static IObservable> WhenPropertyChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6511,35 +6123,15 @@ public static IObservable> WhenPropertyChanged - /// Emits the property value whenever the specified property changes on any item in the cache. - /// Like but emits only the value, discarding the owning item. + /// Watches each item in the collection and notifies when any of them has changed. /// - /// The type of the object (must implement ). + /// The type of the object. /// The type of the key. - /// The type of the monitored property. - /// The source changeset stream. - /// Expression selecting the property to monitor. - /// When true (the default), the current property value is emitted immediately for each item upon subscription. - /// An observable of property values. The owning item is not included; use if you need it. - /// - /// - /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual - /// property subscriptions are silently ignored. If you need to correlate a value back to its source item, - /// use which returns a pair. - /// - /// - /// EventBehavior - /// AddSubscribes to the specified property. If notifyOnInitialValue is true, the current value is emitted immediately. - /// UpdateDisposes the old subscription, subscribes to the new item's property. - /// RemoveDisposes the property subscription. - /// RefreshNo effect on subscriptions. - /// OnErrorPer-item errors silently ignored. Source errors terminate the stream. - /// OnCompletedCompletes when the source completes. - /// - /// - /// - /// - /// + /// The type of the value. + /// The source of . + /// An property accessor. + /// If true the resulting observable includes the initial value. + /// An observable which emits a value when it has changed. public static IObservable WhenValueChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6555,14 +6147,11 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The reasons. + /// The source of . + /// The values reasons. /// An observable which emits a change set with items matching the reasons. /// reasons. /// Must select at least on reason. - /// - /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. - /// public static IObservable> WhereReasonsAre(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6585,14 +6174,11 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The reasons. + /// The source of . + /// The values reasons. /// An observable which emits a change set with items not matching the reasons. /// reasons. /// Must select at least on reason. - /// - /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. - /// public static IObservable> WhereReasonsAreNot(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6610,34 +6196,19 @@ public static IObservable> WhereReasonsAreNot - /// Combines multiple changeset streams using logical XOR (symmetric difference). - /// An item appears downstream only if it exists in exactly one source. + /// Apply a logical Xor operator between the collections. + /// Items which are only in one of the sources are included in the result. /// /// The type of the object. /// The type of the key. - /// The first source changeset stream. - /// Additional changeset streams to combine with. - /// A changeset stream containing items present in exactly one source. - /// - /// - /// Items are tracked via reference counting. An item appears downstream only when exactly one - /// source holds it. Adding the same key from a second source removes it from the result; - /// removing from that second source restores it. - /// - /// - /// EventBehavior - /// AddIf the key is now held by exactly one source, an Add is emitted. If adding causes the count to reach 2+, a Remove is emitted (the item is no longer exclusive). - /// UpdateIf the item is currently downstream (count is 1), an Update is emitted. - /// RemoveReference count decremented. If the count drops to exactly 1, an Add is emitted (the item is now exclusive to one source). If it drops to 0, a Remove is emitted. - /// RefreshIf the item is downstream, a Refresh is forwarded. - /// OnErrorAn error from any source terminates the combined output. - /// OnCompletedThe output completes when all sources have completed. - /// - /// - /// or is null. - /// - /// - /// + /// The source of . + /// The other of streams. + /// An observable which emits a change set. + /// + /// source + /// or + /// others. + /// public static IObservable> Xor(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -6652,9 +6223,19 @@ public static IObservable> Xor(this IOb return source.Combine(CombineOperator.Xor, others); } - /// - /// A fixed collection of changeset streams to combine. - /// This overload accepts a pre-built collection of sources instead of a params array. + /// + /// Apply a logical Xor operator between the collections. + /// Items which are only in one of the sources are included in the result. + /// + /// The type of the object. + /// The type of the key. + /// An of of streams. source. + /// An observable which emits a change set. + /// + /// source + /// or + /// others. + /// public static IObservable> Xor(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -6670,7 +6251,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of of streams. source. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull @@ -6687,7 +6268,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull @@ -6704,7 +6285,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// An of instances. source. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull From 820030bfe01d6a6aacb3390045f675e38a2f219b Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 08:08:44 -0700 Subject: [PATCH 06/23] docs: add documentation skill codifying XML comment standards Defines the complete process for writing DynamicData operator documentation: analysis steps, XML templates for cache/list/multi-source/mutation/non-changeset operators, quality rules for params/seealso/types/tone, batch application guidance, and concrete examples from Filter, MergeChangeSets, OnItemRemoved, and TransformOnObservable. --- .github/skills/add-documentation.md | 284 ++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100644 .github/skills/add-documentation.md diff --git a/.github/skills/add-documentation.md b/.github/skills/add-documentation.md new file mode 100644 index 000000000..2d7f6c7cb --- /dev/null +++ b/.github/skills/add-documentation.md @@ -0,0 +1,284 @@ +# Add Documentation Skill + +## Purpose + +Codifies the process for writing publication-quality XML documentation for DynamicData operators. Use this when adding a new operator, updating an existing operator's docs, or batch-updating docs across a file. + +## When to Use + +- A new operator has been added and needs XML documentation +- An existing operator's behavior has changed and its docs need updating +- A batch documentation pass is needed across multiple operators +- A PR reviewer requests improved documentation + +## Process Overview + +1. **Analyze the implementation** (read the code, don't guess) +2. **Write the XML comments** following the template below +3. **Verify accuracy** by cross-checking claims against the implementation +4. **Build and test** to confirm XML is well-formed + +--- + +## Step 1: Analyze the Implementation + +Read the operator's internal implementation file (in `Cache/Internal/` or `List/Internal/`). For EACH of the following, trace the actual code path: + +### For Cache Operators (`IChangeSet`) +- **Add**: What happens when `ChangeReason.Add` arrives? +- **Update**: What happens when `ChangeReason.Update` arrives? Is `Previous` preserved? +- **Remove**: What happens when `ChangeReason.Remove` arrives? Any cleanup? +- **Refresh**: What happens when `ChangeReason.Refresh` arrives? Re-evaluate? Forward? Drop? Convert to Add/Remove? +- **OnError**: Forwarded? Swallowed? Caught and routed to callback? +- **OnCompleted**: Immediate? Waits for children? Conditional? + +### For List Operators (`IChangeSet`) +- **Add**: Single item added at index +- **AddRange**: Multiple items added at index +- **Replace**: Item at index replaced (cache equivalent of Update) +- **Remove**: Single item removed +- **RemoveRange**: Multiple items removed +- **Moved**: Item moved between indices +- **Refresh**: Signal to re-evaluate +- **Clear**: All items removed +- **OnError**: How errors propagate +- **OnCompleted**: How completion propagates + +### Additional Analysis +- **Multi-source behavior**: For operators with multiple inputs (joins, set ops, MergeManyChangeSets), how are sources synchronized? What if one errors/completes independently? +- **Per-item observable behavior**: For *OnObservable operators, when is the subscription created/disposed? What if the observable never emits? +- **Gotchas**: Anything surprising, non-obvious, or easy to get wrong + +--- + +## Step 2: Write the XML Comments + +### Template for Primary Overloads (Cache) + +```xml +/// +/// [1-3 sentences: what it does and why you'd use it. No behavioral details here.] +/// +/// The type of items in the cache. +/// The type of the key. +/// The source of . +/// An that [what it controls]. +/// [What the return observable emits and what each emission represents.] +/// Thrown when is null. +/// +/// [Detailed explanation: when to use, how it works, what makes this overload different. +/// Multiple paragraphs are fine. This is where the real documentation lives.] +/// +/// EventBehavior +/// Add[Specific behavior. Name output ChangeReasons in bold.] +/// Update[Specific behavior. Mention Previous value handling.] +/// Remove[Specific behavior. Mention cleanup if applicable.] +/// Refresh[Specific behavior. This is often the surprising one.] +/// OnError[Source errors? Child errors? Factory errors?] +/// OnCompleted[Immediate? Waits for children? Conditional?] +/// +/// Worth noting: [Non-obvious behaviors, common mistakes, edge cases.] +/// +/// +/// +/// +/// +``` + +### Template for Primary Overloads (List) + +Same structure, but the event table uses `ListChangeReason` values: + +```xml +/// +/// EventBehavior +/// Add[behavior] +/// AddRange[behavior] +/// Replace[behavior] +/// Remove[behavior] +/// RemoveRange[behavior] +/// Moved[behavior] +/// Refresh[behavior] +/// Clear[behavior] +/// OnError[behavior] +/// OnCompleted[behavior] +/// +``` + +Rows with identical behavior can be combined (e.g., "Remove/RemoveRange/Clear"). + +### Template for Multi-Source Operators + +Use separate labeled tables for each source: + +```xml +/// Source changeset handling (parent events): +/// +/// EventBehavior +/// Add[what happens to subscriptions/state] +/// ... +/// +/// Per-item observable handling: +/// +/// EmissionBehavior +/// First value[what appears downstream] +/// Subsequent values[updates? replacements?] +/// Error[terminates stream? swallowed?] +/// Completed[item freezes? removed?] +/// +``` + +### Template for Secondary (inheritdoc) Overloads + +```xml +/// +/// A that [description specific to this overload]. +/// This overload [omits the key / accepts a simpler factory / etc]. Delegates to . +``` + +### Template for Mutation Helpers (AddOrUpdate, Remove, Clear, Refresh) + +The event table describes what changeset is PRODUCED, not consumed: + +```xml +/// +/// EventBehavior +/// AddProduced when the key does not already exist in the cache. +/// UpdateProduced when the key already exists. +/// OtherNot produced by this method. +/// +``` + +### Template for Non-Changeset Operators (MergeMany, Watch, Property Observers) + +The event table describes how source changeset events affect subscriptions: + +```xml +/// +/// EventBehavior +/// AddSubscribes to per-item observable. +/// UpdateDisposes old subscription, subscribes to new. +/// RemoveDisposes subscription. +/// RefreshNo effect on subscriptions. +/// OnError[child errors swallowed? forwarded?] +/// OnCompleted[waits for children? immediate?] +/// +``` + +--- + +## Step 3: Quality Rules + +### Param Tags +- Every `` MUST mention and link its type via `` +- Read the actual method signature to get the real type +- `Func<>` and `Action<>` link to `Func{T, TResult}` or `Action{T}` +- `IObservable<>` links to `IObservable{T}` +- `IComparer<>` and `IEqualityComparer<>` link appropriately +- `IScheduler` links directly +- `bool`, `int`, `string[]` params: no type link needed (self-evident) + +### SeeAlso Tags +Every operator MUST cross-reference: +- **Other overloads in the same set** (bidirectional: primary links to all secondaries, each secondary links back to primary) +- **Safe variant** if one exists (Transform <-> TransformSafe) +- **Async variant** if one exists (Transform <-> TransformAsync) +- **Similar operators** (Filter <-> FilterImmutable <-> FilterOnObservable) +- **Complementary operators** often used together (Filter <-> AutoRefresh, Sort <-> Bind) +- **Commonly confused operators** (MergeMany vs MergeManyChangeSets vs MergeChangeSets) + +### Type References +- Types and interfaces mentioned in comments MUST use ``, not `...` +- Method names, event names, and property names use `...` (contextual, not discoverable types) +- Internal-only types MUST NOT appear in public documentation. Describe behavior, not implementation. + +### Tone +- Summary: 1-3 sentences only. All behavioral detail in ``. +- NEVER use em dashes (the long dash character). Use colons, commas, parentheses, or restructure. +- No emoji. +- No filler words: "comprehensive", "robust", "seamlessly", "leverage", "utilize", "facilitate". +- Be specific about outcomes: "an **Update** is emitted" not "the change is propagated". +- Use "Worth noting" (not "Gotchas") for non-obvious behavior sections. + +### Accuracy +- Every behavioral claim MUST be traceable to the implementation code. +- If uncertain about a behavior, read the code. Do not guess from naming conventions. +- The Refresh row is the most commonly surprising one. Always verify it. + +--- + +## Step 4: Build and Verify + +```bash +dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framework net9.0 +``` + +Check for: +- CS1570/CS1571/CS1572/CS1573 warnings (malformed XML) +- CS1574 warnings (unresolved cref attributes) +- 0 errors + +--- + +## Batch Application + +When documenting multiple operators at once: + +1. **Dispatch analysis agents in parallel** (read-only explore agents) to trace implementations. Group related operators: + - Transform family (Transform, TransformSafe, TransformAsync, TransformImmutable, etc.) + - Filter family (Filter, FilterImmutable, FilterOnObservable) + - Merge family (MergeMany, MergeChangeSets, MergeManyChangeSets) + - Set operations (And, Or, Except, Xor) + - Joins (InnerJoin, LeftJoin, RightJoin, FullJoin + Many variants) + - Lifecycle (OnItemAdded, OnItemUpdated, OnItemRemoved, OnItemRefreshed, ForEachChange) + +2. **Apply edits yourself or via a single agent** (never multiple agents editing the same file simultaneously: they will clobber each other's work). + +3. **After editing, verify**: + - Build passes + - No em dashes: search for Unicode character 0x2014 + - No old-style "The source." params remaining + - All event tables use `Event` header + - Spot-check 5-10 operators against their implementation + +4. **Diff against main** to confirm no important details were lost from the original comments. Preserve all existing useful information (additive only). + +--- + +## Examples + +### Good: Filter Refresh (shows re-evaluation with 4 outcomes) + +```xml +/// RefreshRe-evaluated. Now passes but didn't before: Add. +/// Still passes: Refresh forwarded. No longer passes: Remove. Still fails: dropped. +``` + +### Good: MergeChangeSets Remove (shows cross-source fallback) + +```xml +/// RemoveIf the removed value was published downstream, all remaining +/// sources are scanned for the same key. If another source holds it, an Update is emitted with the +/// replacement value (selected by comparer if provided). If no source holds the key, a Remove is +/// emitted. +``` + +### Good: OnItemRemoved (shows disposal behavior) + +```xml +/// OnCompletedForwarded. When invokeOnUnsubscribe is true, disposing the +/// subscription also invokes the callback for every item still in the cache. +``` + +### Good: TransformOnObservable per-item table + +```xml +/// Per-item observable handling: +/// +/// EmissionBehavior +/// First valueThe transformed item appears downstream as an Add. +/// Subsequent valuesEach new value replaces the previous: an Update is emitted. +/// ErrorTerminates the entire output stream. +/// CompletedItem remains at last value. No further updates possible. +/// +``` \ No newline at end of file From b1df27a44cb2b148d570c03ffd10e66f36d4c922 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 09:52:15 -0700 Subject: [PATCH 07/23] docs: add documentation skill for XML comment standards Reusable skill (.github/skills/add-documentation/SKILL.md) codifying the process for writing publication-quality XML documentation for any DynamicData public API: operators, classes, interfaces, enums. Covers analysis, writing templates (cache/list/multi-source/mutation/non-changeset), quality rules (param type linking, bidirectional seealso, tone), batch application, and common mistakes. Replaces the incorrectly placed file. --- .github/skills/add-documentation.md | 284 ---------------------- .github/skills/add-documentation/SKILL.md | 143 +++++++++++ 2 files changed, 143 insertions(+), 284 deletions(-) delete mode 100644 .github/skills/add-documentation.md create mode 100644 .github/skills/add-documentation/SKILL.md diff --git a/.github/skills/add-documentation.md b/.github/skills/add-documentation.md deleted file mode 100644 index 2d7f6c7cb..000000000 --- a/.github/skills/add-documentation.md +++ /dev/null @@ -1,284 +0,0 @@ -# Add Documentation Skill - -## Purpose - -Codifies the process for writing publication-quality XML documentation for DynamicData operators. Use this when adding a new operator, updating an existing operator's docs, or batch-updating docs across a file. - -## When to Use - -- A new operator has been added and needs XML documentation -- An existing operator's behavior has changed and its docs need updating -- A batch documentation pass is needed across multiple operators -- A PR reviewer requests improved documentation - -## Process Overview - -1. **Analyze the implementation** (read the code, don't guess) -2. **Write the XML comments** following the template below -3. **Verify accuracy** by cross-checking claims against the implementation -4. **Build and test** to confirm XML is well-formed - ---- - -## Step 1: Analyze the Implementation - -Read the operator's internal implementation file (in `Cache/Internal/` or `List/Internal/`). For EACH of the following, trace the actual code path: - -### For Cache Operators (`IChangeSet`) -- **Add**: What happens when `ChangeReason.Add` arrives? -- **Update**: What happens when `ChangeReason.Update` arrives? Is `Previous` preserved? -- **Remove**: What happens when `ChangeReason.Remove` arrives? Any cleanup? -- **Refresh**: What happens when `ChangeReason.Refresh` arrives? Re-evaluate? Forward? Drop? Convert to Add/Remove? -- **OnError**: Forwarded? Swallowed? Caught and routed to callback? -- **OnCompleted**: Immediate? Waits for children? Conditional? - -### For List Operators (`IChangeSet`) -- **Add**: Single item added at index -- **AddRange**: Multiple items added at index -- **Replace**: Item at index replaced (cache equivalent of Update) -- **Remove**: Single item removed -- **RemoveRange**: Multiple items removed -- **Moved**: Item moved between indices -- **Refresh**: Signal to re-evaluate -- **Clear**: All items removed -- **OnError**: How errors propagate -- **OnCompleted**: How completion propagates - -### Additional Analysis -- **Multi-source behavior**: For operators with multiple inputs (joins, set ops, MergeManyChangeSets), how are sources synchronized? What if one errors/completes independently? -- **Per-item observable behavior**: For *OnObservable operators, when is the subscription created/disposed? What if the observable never emits? -- **Gotchas**: Anything surprising, non-obvious, or easy to get wrong - ---- - -## Step 2: Write the XML Comments - -### Template for Primary Overloads (Cache) - -```xml -/// -/// [1-3 sentences: what it does and why you'd use it. No behavioral details here.] -/// -/// The type of items in the cache. -/// The type of the key. -/// The source of . -/// An that [what it controls]. -/// [What the return observable emits and what each emission represents.] -/// Thrown when is null. -/// -/// [Detailed explanation: when to use, how it works, what makes this overload different. -/// Multiple paragraphs are fine. This is where the real documentation lives.] -/// -/// EventBehavior -/// Add[Specific behavior. Name output ChangeReasons in bold.] -/// Update[Specific behavior. Mention Previous value handling.] -/// Remove[Specific behavior. Mention cleanup if applicable.] -/// Refresh[Specific behavior. This is often the surprising one.] -/// OnError[Source errors? Child errors? Factory errors?] -/// OnCompleted[Immediate? Waits for children? Conditional?] -/// -/// Worth noting: [Non-obvious behaviors, common mistakes, edge cases.] -/// -/// -/// -/// -/// -``` - -### Template for Primary Overloads (List) - -Same structure, but the event table uses `ListChangeReason` values: - -```xml -/// -/// EventBehavior -/// Add[behavior] -/// AddRange[behavior] -/// Replace[behavior] -/// Remove[behavior] -/// RemoveRange[behavior] -/// Moved[behavior] -/// Refresh[behavior] -/// Clear[behavior] -/// OnError[behavior] -/// OnCompleted[behavior] -/// -``` - -Rows with identical behavior can be combined (e.g., "Remove/RemoveRange/Clear"). - -### Template for Multi-Source Operators - -Use separate labeled tables for each source: - -```xml -/// Source changeset handling (parent events): -/// -/// EventBehavior -/// Add[what happens to subscriptions/state] -/// ... -/// -/// Per-item observable handling: -/// -/// EmissionBehavior -/// First value[what appears downstream] -/// Subsequent values[updates? replacements?] -/// Error[terminates stream? swallowed?] -/// Completed[item freezes? removed?] -/// -``` - -### Template for Secondary (inheritdoc) Overloads - -```xml -/// -/// A that [description specific to this overload]. -/// This overload [omits the key / accepts a simpler factory / etc]. Delegates to . -``` - -### Template for Mutation Helpers (AddOrUpdate, Remove, Clear, Refresh) - -The event table describes what changeset is PRODUCED, not consumed: - -```xml -/// -/// EventBehavior -/// AddProduced when the key does not already exist in the cache. -/// UpdateProduced when the key already exists. -/// OtherNot produced by this method. -/// -``` - -### Template for Non-Changeset Operators (MergeMany, Watch, Property Observers) - -The event table describes how source changeset events affect subscriptions: - -```xml -/// -/// EventBehavior -/// AddSubscribes to per-item observable. -/// UpdateDisposes old subscription, subscribes to new. -/// RemoveDisposes subscription. -/// RefreshNo effect on subscriptions. -/// OnError[child errors swallowed? forwarded?] -/// OnCompleted[waits for children? immediate?] -/// -``` - ---- - -## Step 3: Quality Rules - -### Param Tags -- Every `` MUST mention and link its type via `` -- Read the actual method signature to get the real type -- `Func<>` and `Action<>` link to `Func{T, TResult}` or `Action{T}` -- `IObservable<>` links to `IObservable{T}` -- `IComparer<>` and `IEqualityComparer<>` link appropriately -- `IScheduler` links directly -- `bool`, `int`, `string[]` params: no type link needed (self-evident) - -### SeeAlso Tags -Every operator MUST cross-reference: -- **Other overloads in the same set** (bidirectional: primary links to all secondaries, each secondary links back to primary) -- **Safe variant** if one exists (Transform <-> TransformSafe) -- **Async variant** if one exists (Transform <-> TransformAsync) -- **Similar operators** (Filter <-> FilterImmutable <-> FilterOnObservable) -- **Complementary operators** often used together (Filter <-> AutoRefresh, Sort <-> Bind) -- **Commonly confused operators** (MergeMany vs MergeManyChangeSets vs MergeChangeSets) - -### Type References -- Types and interfaces mentioned in comments MUST use ``, not `...` -- Method names, event names, and property names use `...` (contextual, not discoverable types) -- Internal-only types MUST NOT appear in public documentation. Describe behavior, not implementation. - -### Tone -- Summary: 1-3 sentences only. All behavioral detail in ``. -- NEVER use em dashes (the long dash character). Use colons, commas, parentheses, or restructure. -- No emoji. -- No filler words: "comprehensive", "robust", "seamlessly", "leverage", "utilize", "facilitate". -- Be specific about outcomes: "an **Update** is emitted" not "the change is propagated". -- Use "Worth noting" (not "Gotchas") for non-obvious behavior sections. - -### Accuracy -- Every behavioral claim MUST be traceable to the implementation code. -- If uncertain about a behavior, read the code. Do not guess from naming conventions. -- The Refresh row is the most commonly surprising one. Always verify it. - ---- - -## Step 4: Build and Verify - -```bash -dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framework net9.0 -``` - -Check for: -- CS1570/CS1571/CS1572/CS1573 warnings (malformed XML) -- CS1574 warnings (unresolved cref attributes) -- 0 errors - ---- - -## Batch Application - -When documenting multiple operators at once: - -1. **Dispatch analysis agents in parallel** (read-only explore agents) to trace implementations. Group related operators: - - Transform family (Transform, TransformSafe, TransformAsync, TransformImmutable, etc.) - - Filter family (Filter, FilterImmutable, FilterOnObservable) - - Merge family (MergeMany, MergeChangeSets, MergeManyChangeSets) - - Set operations (And, Or, Except, Xor) - - Joins (InnerJoin, LeftJoin, RightJoin, FullJoin + Many variants) - - Lifecycle (OnItemAdded, OnItemUpdated, OnItemRemoved, OnItemRefreshed, ForEachChange) - -2. **Apply edits yourself or via a single agent** (never multiple agents editing the same file simultaneously: they will clobber each other's work). - -3. **After editing, verify**: - - Build passes - - No em dashes: search for Unicode character 0x2014 - - No old-style "The source." params remaining - - All event tables use `Event` header - - Spot-check 5-10 operators against their implementation - -4. **Diff against main** to confirm no important details were lost from the original comments. Preserve all existing useful information (additive only). - ---- - -## Examples - -### Good: Filter Refresh (shows re-evaluation with 4 outcomes) - -```xml -/// RefreshRe-evaluated. Now passes but didn't before: Add. -/// Still passes: Refresh forwarded. No longer passes: Remove. Still fails: dropped. -``` - -### Good: MergeChangeSets Remove (shows cross-source fallback) - -```xml -/// RemoveIf the removed value was published downstream, all remaining -/// sources are scanned for the same key. If another source holds it, an Update is emitted with the -/// replacement value (selected by comparer if provided). If no source holds the key, a Remove is -/// emitted. -``` - -### Good: OnItemRemoved (shows disposal behavior) - -```xml -/// OnCompletedForwarded. When invokeOnUnsubscribe is true, disposing the -/// subscription also invokes the callback for every item still in the cache. -``` - -### Good: TransformOnObservable per-item table - -```xml -/// Per-item observable handling: -/// -/// EmissionBehavior -/// First valueThe transformed item appears downstream as an Add. -/// Subsequent valuesEach new value replaces the previous: an Update is emitted. -/// ErrorTerminates the entire output stream. -/// CompletedItem remains at last value. No further updates possible. -/// -``` \ No newline at end of file diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md new file mode 100644 index 000000000..7e590725d --- /dev/null +++ b/.github/skills/add-documentation/SKILL.md @@ -0,0 +1,143 @@ +--- +name: add-documentation +description: Use when adding or updating XML documentation for any public API in DynamicData, including new operators, changed behavior, batch documentation passes, or PR reviewer requests for improved docs. Covers extension methods, public classes, interfaces, enums, and any member visible in the published API reference. +--- + +# Add Documentation + +## Overview + +Write publication-quality XML documentation for DynamicData public APIs. Every behavioral claim must be traced from the implementation source, not guessed from naming conventions. The documentation will be extracted as HTML and published on the ReactiveUI docs site. + +## When to Use + +- New operator or public API added +- Existing operator's behavior changed +- Batch documentation pass across a file +- PR reviewer requests improved documentation +- Any public type, interface, enum, or member needs docs + +## Process + +### 1. Analyze the Implementation + +Read the actual source code. For every public member, trace the code paths. + +**For changeset operators** (methods extending `IObservable>`): + +Trace what happens for each change reason the operator handles. Cache operators use `ChangeReason` (Add, Update, Remove, Refresh). List operators use `ListChangeReason` (Add, AddRange, Replace, Remove, RemoveRange, Moved, Refresh, Clear). Also trace OnError and OnCompleted propagation. + +Key questions per operator: +- Does Refresh re-evaluate? Forward as-is? Drop? Convert to Add/Remove? +- Are child/per-item errors swallowed or forwarded? +- Does OnCompleted wait for child subscriptions? +- What cleanup happens on Remove or disposal? + +**For non-changeset public APIs** (classes, interfaces, enums, static helpers): + +Document the contract: what does each public member do, what are the preconditions, what does it return, what exceptions can it throw. + +### 2. Write the XML Comments + +#### Summary Tag +1-3 sentences only. What it does and why you'd use it. No behavioral details here; those go in remarks. + +#### Param Tags +Every `` MUST mention and link its type: +```xml +/// The source of . +/// An that determines sort order. +/// An for timing. Defaults to . +``` +Exempt: `bool`, `int`, `string` params where the type is self-evident. + +#### Event Table (changeset operators) +Every changeset-processing operator gets a `` inside ``: + +```xml +/// +/// EventBehavior +/// Add[specific outcome, bold output ChangeReasons] +/// ...OnError and OnCompleted rows... +/// +``` + +Cache operators: rows for Add, Update, Remove, Refresh, OnError, OnCompleted. +List operators: rows for Add, AddRange, Replace, Remove, RemoveRange, Moved, Refresh, Clear, OnError, OnCompleted. Combine rows with identical behavior (e.g., "Remove/RemoveRange/Clear"). + +**Multi-source operators** (joins, set ops, MergeManyChangeSets, *OnObservable): use separate labeled tables: +```xml +/// Source changeset handling (parent events): +/// ... +/// Per-item observable handling: +/// ... +``` + +**Mutation helpers** (AddOrUpdate, Remove, Clear, etc.): table describes what changeset is PRODUCED. + +**Non-changeset output operators** (MergeMany, Watch, property observers): table describes how source events affect subscriptions. + +#### Worth Noting Section +Add `Worth noting: ...` for non-obvious behavior: disposal callbacks, silent error swallowing, items invisible until first emission, index-stripping, etc. + +#### SeeAlso Tags +Every operator MUST cross-reference (bidirectional for overload sets): +- Other overloads in the same set (primary links to all, each secondary links back) +- Safe/async/immutable variants +- Similar operators solving related problems +- Complementary operators often used together +- Commonly confused operators + +#### Type References +Types and interfaces: ``. Method names and events: `Adapt`. Internal-only types MUST NOT appear. Describe behavior, not implementation. + +#### InheritDoc for Secondary Overloads +```xml +/// +/// A that [specific difference]. +/// This overload [what differs]. Delegates to . +``` + +### 3. Verify + +```bash +dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framework net9.0 +``` +- 0 errors, no new CS1574 warnings (unresolved cref) +- No em dashes (Unicode 0x2014) +- No "The source." remaining +- All tables use `Event` +- Spot-check 3-5 operators against their implementation + +### 4. Diff Against Main + +Confirm no important details were lost from original comments. The overhaul must be additive. + +## Tone Rules + +- No em dashes. Use colons, commas, parentheses. +- No emoji. +- No filler: "comprehensive", "robust", "seamlessly", "leverage", "utilize", "facilitate". +- Be specific: "an **Update** is emitted" not "the change is propagated". +- Use "Worth noting" for non-obvious behavior (not "Gotchas"). + +## Batch Application + +For large-scale passes across many operators: + +1. Dispatch parallel **read-only** agents to analyze implementations (group by family: Transform, Filter, Merge, etc.) +2. Apply edits via a **single agent or yourself** (multiple agents editing one file will clobber each other) +3. Build, audit metrics (table count, seealso count, em dashes, old params), spot-check accuracy +4. Diff against main for lost details + +## Common Mistakes + +| Mistake | Fix | +|---------|-----| +| Guessing behavior from method name | Read the implementation file | +| Missing Refresh row (the tricky one) | Always trace Refresh explicitly | +| `IComparer` for a type | `` | +| Referencing internal types | Describe behavior instead | +| One-way seealso links | Make them bidirectional | +| Multiple agents editing same file | One editor at a time | +| Tables with only 4 cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear too | \ No newline at end of file From 3e032c0424dc6c042f7df2be2b2dd5fe09673c70 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:04:19 -0700 Subject: [PATCH 08/23] docs: expand documentation skill with examples and decision criteria Add before/after example (Filter), template selection table, emphasize additive-only rule, and note about Refresh behavior variance across operators. Restructure for clarity. --- .github/skills/add-documentation/SKILL.md | 129 ++++++++++++++++++---- 1 file changed, 105 insertions(+), 24 deletions(-) diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md index 7e590725d..0fc7e42e0 100644 --- a/.github/skills/add-documentation/SKILL.md +++ b/.github/skills/add-documentation/SKILL.md @@ -17,68 +17,105 @@ Write publication-quality XML documentation for DynamicData public APIs. Every b - PR reviewer requests improved documentation - Any public type, interface, enum, or member needs docs +## Core Rule: Additive Only + +Never remove existing useful information from comments. You are adding detail, not replacing it. After making changes, diff against main to confirm nothing substantive was lost. If the old docs contained a behavioral detail, a parameter constraint, or a usage note, it must survive in the new version. + ## Process ### 1. Analyze the Implementation -Read the actual source code. For every public member, trace the code paths. +Read the actual source code. For every public member, trace each code path. Do not guess from method names or parameter names. **For changeset operators** (methods extending `IObservable>`): Trace what happens for each change reason the operator handles. Cache operators use `ChangeReason` (Add, Update, Remove, Refresh). List operators use `ListChangeReason` (Add, AddRange, Replace, Remove, RemoveRange, Moved, Refresh, Clear). Also trace OnError and OnCompleted propagation. Key questions per operator: -- Does Refresh re-evaluate? Forward as-is? Drop? Convert to Add/Remove? -- Are child/per-item errors swallowed or forwarded? -- Does OnCompleted wait for child subscriptions? +- What does each change reason produce downstream? Name the exact output ChangeReason. +- Are there conditional outcomes? (e.g., Filter's Update has four possible results depending on old/new predicate evaluation) +- Does the operator create per-item subscriptions? When are they created and disposed? - What cleanup happens on Remove or disposal? +- Are errors from child subscriptions forwarded or swallowed? +- Does OnCompleted wait for child subscriptions or forward immediately? + +Pay special attention to Refresh: its behavior varies significantly between operators. Some re-evaluate (Filter), some forward as-is (Transform by default), some drop entirely (FilterImmutable, TransformImmutable), and some convert to other change types. But all change reasons deserve the same careful tracing. **For non-changeset public APIs** (classes, interfaces, enums, static helpers): Document the contract: what does each public member do, what are the preconditions, what does it return, what exceptions can it throw. -### 2. Write the XML Comments +### 2. Choose a Template + +| The method... | Use this template | +|---|---| +| Extends `IObservable` and produces `IObservable` | Changeset operator (cache or list) | +| Has multiple input sources (joins, set ops, *OnObservable) | Multi-source operator (separate tables per source) | +| Extends `ISourceCache`/`ISourceList` and returns void | Mutation helper (table describes what's produced) | +| Extends `IObservable` but produces non-changeset output (`IObservable`, `IObservable`, etc.) | Non-changeset operator (table describes subscription lifecycle) | +| Is a class, interface, enum, or other non-extension member | Standard XML docs (summary, params, returns, remarks) | + +### 3. Write the XML Comments #### Summary Tag 1-3 sentences only. What it does and why you'd use it. No behavioral details here; those go in remarks. #### Param Tags -Every `` MUST mention and link its type: +Every `` MUST mention and link its type via ``: ```xml /// The source of . /// An that determines sort order. /// An for timing. Defaults to . +/// A that transforms each source item. ``` Exempt: `bool`, `int`, `string` params where the type is self-evident. #### Event Table (changeset operators) -Every changeset-processing operator gets a `` inside ``: +Every changeset-processing operator gets a `` inside ``. +Cache operators use these rows: ```xml /// /// EventBehavior -/// Add[specific outcome, bold output ChangeReasons] -/// ...OnError and OnCompleted rows... +/// Add[specific outcome] +/// Update[specific outcome] +/// Remove[specific outcome] +/// Refresh[specific outcome] +/// OnError[forwarded? swallowed? conditional?] +/// OnCompleted[immediate? waits? conditional?] /// ``` -Cache operators: rows for Add, Update, Remove, Refresh, OnError, OnCompleted. -List operators: rows for Add, AddRange, Replace, Remove, RemoveRange, Moved, Refresh, Clear, OnError, OnCompleted. Combine rows with identical behavior (e.g., "Remove/RemoveRange/Clear"). +List operators include the additional list-specific reasons: +```xml +/// AddRange[specific outcome] +/// Replace[specific outcome] +/// RemoveRange[specific outcome] +/// Moved[specific outcome] +/// Clear[specific outcome] +``` +Combine rows with identical behavior (e.g., "Remove/RemoveRange/Clear"). -**Multi-source operators** (joins, set ops, MergeManyChangeSets, *OnObservable): use separate labeled tables: +**Multi-source operators** use separate labeled tables: ```xml /// Source changeset handling (parent events): /// ... /// Per-item observable handling: -/// ... +/// +/// EmissionBehavior +/// First value[what appears downstream] +/// Subsequent values[updates? replacements?] +/// Error[terminates? swallowed?] +/// Completed[freezes? removed?] +/// ``` -**Mutation helpers** (AddOrUpdate, Remove, Clear, etc.): table describes what changeset is PRODUCED. +**Mutation helpers** describe what changeset is PRODUCED (not consumed). -**Non-changeset output operators** (MergeMany, Watch, property observers): table describes how source events affect subscriptions. +**Non-changeset output operators** describe how source events affect internal subscriptions. #### Worth Noting Section -Add `Worth noting: ...` for non-obvious behavior: disposal callbacks, silent error swallowing, items invisible until first emission, index-stripping, etc. +Add `Worth noting: ...` for non-obvious behavior: disposal callbacks firing for all tracked items, silent error swallowing, items invisible until first emission, index-stripping, default parameter effects, etc. #### SeeAlso Tags Every operator MUST cross-reference (bidirectional for overload sets): @@ -89,7 +126,9 @@ Every operator MUST cross-reference (bidirectional for overload sets): - Commonly confused operators #### Type References -Types and interfaces: ``. Method names and events: `Adapt`. Internal-only types MUST NOT appear. Describe behavior, not implementation. +- Types and interfaces: `` (linked, discoverable) +- Method names, event names, property names: `Adapt` (inline code, contextual) +- Internal-only types: MUST NOT appear. Describe behavior, not implementation. #### InheritDoc for Secondary Overloads ```xml @@ -98,7 +137,7 @@ Types and interfaces: ``. Method names and events: `This overload [what differs]. Delegates to . ``` -### 3. Verify +### 4. Verify ```bash dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framework net9.0 @@ -108,10 +147,50 @@ dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framew - No "The source." remaining - All tables use `Event` - Spot-check 3-5 operators against their implementation +- Diff against main: confirm no existing useful information was lost -### 4. Diff Against Main +## Before and After Example -Confirm no important details were lost from original comments. The overhaul must be additive. +**BEFORE** (typical old-style doc): +```xml +/// +/// Filters the specified source. +/// +/// The type of the object. +/// The type of the key. +/// The source. +/// The filter. +/// An observable which emits change sets. +``` + +**AFTER** (publication-quality): +```xml +/// +/// Filters items from the source changeset stream using a static predicate. +/// Only items satisfying are included downstream. +/// +/// The type of items in the cache. +/// The type of the key. +/// The source of to filter. +/// A predicate. Items returning true are included. +/// A changeset stream containing only items that satisfy . +/// +/// Use this overload when the predicate is fixed for the subscription's lifetime. +/// +/// EventBehavior +/// AddPredicate evaluated. If passes, Add emitted. Otherwise dropped. +/// UpdateRe-evaluated. Both pass: Update. New passes, old didn't: Add. Old passed, new doesn't: Remove. Neither: dropped. +/// RemoveIf downstream, Remove emitted. Otherwise dropped. +/// RefreshRe-evaluated. Now passes but didn't: Add. Still passes: Refresh forwarded. No longer passes: Remove. Still fails: dropped. +/// OnErrorForwarded. +/// OnCompletedForwarded. +/// +/// Worth noting: Refresh events trigger re-evaluation, which can promote or demote items. +/// +/// +/// +/// +``` ## Tone Rules @@ -120,13 +199,14 @@ Confirm no important details were lost from original comments. The overhaul must - No filler: "comprehensive", "robust", "seamlessly", "leverage", "utilize", "facilitate". - Be specific: "an **Update** is emitted" not "the change is propagated". - Use "Worth noting" for non-obvious behavior (not "Gotchas"). +- Write like a senior developer, not a marketing brochure. ## Batch Application For large-scale passes across many operators: 1. Dispatch parallel **read-only** agents to analyze implementations (group by family: Transform, Filter, Merge, etc.) -2. Apply edits via a **single agent or yourself** (multiple agents editing one file will clobber each other) +2. Apply edits via a **single agent or yourself** (multiple agents editing one file will clobber each other's work) 3. Build, audit metrics (table count, seealso count, em dashes, old params), spot-check accuracy 4. Diff against main for lost details @@ -135,9 +215,10 @@ For large-scale passes across many operators: | Mistake | Fix | |---------|-----| | Guessing behavior from method name | Read the implementation file | -| Missing Refresh row (the tricky one) | Always trace Refresh explicitly | | `IComparer` for a type | `` | -| Referencing internal types | Describe behavior instead | +| Referencing internal types in public docs | Describe behavior instead | | One-way seealso links | Make them bidirectional | | Multiple agents editing same file | One editor at a time | -| Tables with only 4 cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear too | \ No newline at end of file +| Removing existing useful information | Additive only; diff against main | +| Tables with only cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear too | +| Params missing type links | Every param mentions and links its type | \ No newline at end of file From b883f3b3b65ffe848474d474f8d65c46c8b6c119 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:12:06 -0700 Subject: [PATCH 09/23] docs: inline unified template in documentation skill Replace scattered template fragments with a single copy-and-delete template covering all operator categories (cache, list, multi-source, mutation, non-changeset). One file, no duplication, delete the sections that don't apply. --- .github/skills/add-documentation/SKILL.md | 224 ++++++++++------------ 1 file changed, 100 insertions(+), 124 deletions(-) diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md index 0fc7e42e0..028f29ac4 100644 --- a/.github/skills/add-documentation/SKILL.md +++ b/.github/skills/add-documentation/SKILL.md @@ -19,87 +19,57 @@ Write publication-quality XML documentation for DynamicData public APIs. Every b ## Core Rule: Additive Only -Never remove existing useful information from comments. You are adding detail, not replacing it. After making changes, diff against main to confirm nothing substantive was lost. If the old docs contained a behavioral detail, a parameter constraint, or a usage note, it must survive in the new version. +Never remove existing useful information from comments. After making changes, diff against main to confirm nothing substantive was lost. -## Process - -### 1. Analyze the Implementation - -Read the actual source code. For every public member, trace each code path. Do not guess from method names or parameter names. - -**For changeset operators** (methods extending `IObservable>`): - -Trace what happens for each change reason the operator handles. Cache operators use `ChangeReason` (Add, Update, Remove, Refresh). List operators use `ListChangeReason` (Add, AddRange, Replace, Remove, RemoveRange, Moved, Refresh, Clear). Also trace OnError and OnCompleted propagation. - -Key questions per operator: -- What does each change reason produce downstream? Name the exact output ChangeReason. -- Are there conditional outcomes? (e.g., Filter's Update has four possible results depending on old/new predicate evaluation) -- Does the operator create per-item subscriptions? When are they created and disposed? -- What cleanup happens on Remove or disposal? -- Are errors from child subscriptions forwarded or swallowed? -- Does OnCompleted wait for child subscriptions or forward immediately? +## Unified Template -Pay special attention to Refresh: its behavior varies significantly between operators. Some re-evaluate (Filter), some forward as-is (Transform by default), some drop entirely (FilterImmutable, TransformImmutable), and some convert to other change types. But all change reasons deserve the same careful tracing. +Start from this template for any primary overload. Delete sections that do not apply. -**For non-changeset public APIs** (classes, interfaces, enums, static helpers): - -Document the contract: what does each public member do, what are the preconditions, what does it return, what exceptions can it throw. - -### 2. Choose a Template - -| The method... | Use this template | -|---|---| -| Extends `IObservable` and produces `IObservable` | Changeset operator (cache or list) | -| Has multiple input sources (joins, set ops, *OnObservable) | Multi-source operator (separate tables per source) | -| Extends `ISourceCache`/`ISourceList` and returns void | Mutation helper (table describes what's produced) | -| Extends `IObservable` but produces non-changeset output (`IObservable`, `IObservable`, etc.) | Non-changeset operator (table describes subscription lifecycle) | -| Is a class, interface, enum, or other non-extension member | Standard XML docs (summary, params, returns, remarks) | - -### 3. Write the XML Comments - -#### Summary Tag -1-3 sentences only. What it does and why you'd use it. No behavioral details here; those go in remarks. - -#### Param Tags -Every `` MUST mention and link its type via ``: ```xml +/// +/// [1-3 sentences: what it does, why you'd use it. No behavioral details.] +/// +/// The type of items. +/// The type of the key. /// The source of . -/// An that determines sort order. -/// An for timing. Defaults to . -/// A that transforms each source item. -``` -Exempt: `bool`, `int`, `string` params where the type is self-evident. - -#### Event Table (changeset operators) -Every changeset-processing operator gets a `` inside ``. - -Cache operators use these rows: -```xml +/// An that [what it controls]. +/// [What it emits and what each emission represents.] +/// Thrown when is null. +/// +/// [When to use. How it differs from alternatives. Multiple paragraphs fine.] +/// +/// +/// +/// +/// +/// /// /// EventBehavior -/// Add[specific outcome] +/// +/// Add[specific outcome, bold output reasons] /// Update[specific outcome] -/// Remove[specific outcome] -/// Refresh[specific outcome] -/// OnError[forwarded? swallowed? conditional?] -/// OnCompleted[immediate? waits? conditional?] -/// -``` - -List operators include the additional list-specific reasons: -```xml +/// Remove[specific outcome, mention cleanup] +/// Refresh[specific outcome, trace carefully] +/// /// AddRange[specific outcome] -/// Replace[specific outcome] +/// Replace[list equivalent of Update] /// RemoveRange[specific outcome] /// Moved[specific outcome] /// Clear[specific outcome] -``` -Combine rows with identical behavior (e.g., "Remove/RemoveRange/Clear"). - -**Multi-source operators** use separate labeled tables: -```xml +/// +/// OnError[forwarded? swallowed? conditional?] +/// OnCompleted[immediate? waits for children?] +/// +/// +/// /// Source changeset handling (parent events): -/// ... +/// +/// EventBehavior +/// Add[subscribes to child / creates state] +/// Update[disposes old, subscribes to new] +/// Remove[disposes, emits downstream removes] +/// Refresh[no effect / re-evaluates] +/// /// Per-item observable handling: /// /// EmissionBehavior @@ -108,56 +78,75 @@ Combine rows with identical behavior (e.g., "Remove/RemoveRange/Clear"). /// Error[terminates? swallowed?] /// Completed[freezes? removed?] /// +/// +/// Worth noting: [Non-obvious behavior, edge cases, disposal semantics.] +/// +/// +/// +/// +/// ``` -**Mutation helpers** describe what changeset is PRODUCED (not consumed). - -**Non-changeset output operators** describe how source events affect internal subscriptions. - -#### Worth Noting Section -Add `Worth noting: ...` for non-obvious behavior: disposal callbacks firing for all tracked items, silent error swallowing, items invisible until first emission, index-stripping, default parameter effects, etc. - -#### SeeAlso Tags -Every operator MUST cross-reference (bidirectional for overload sets): -- Other overloads in the same set (primary links to all, each secondary links back) -- Safe/async/immutable variants -- Similar operators solving related problems -- Complementary operators often used together -- Commonly confused operators - -#### Type References -- Types and interfaces: `` (linked, discoverable) -- Method names, event names, property names: `Adapt` (inline code, contextual) -- Internal-only types: MUST NOT appear. Describe behavior, not implementation. - -#### InheritDoc for Secondary Overloads +For **secondary overloads** that delegate to a primary: ```xml /// /// A that [specific difference]. /// This overload [what differs]. Delegates to . ``` +## Process + +### 1. Analyze the Implementation + +Read the actual source code. Trace each code path for every change reason the operator handles. + +Key questions: +- What does each change reason produce downstream? Name the exact output. +- Are there conditional outcomes? (e.g., Filter's Update has four possible results) +- Does the operator create per-item subscriptions? When created/disposed? +- Are errors from child subscriptions forwarded or swallowed? +- Does OnCompleted wait for child subscriptions? + +Refresh behavior varies significantly between operators: some re-evaluate (Filter), some forward as-is (Transform by default), some drop (FilterImmutable), some convert to other change types. But all change reasons deserve the same careful tracing. + +### 2. Choose What to Include + +| The method... | Template sections to use | +|---|---| +| Extends `IObservable`, produces `IObservable` | Single event table (cache or list rows) | +| Has multiple input sources or per-item observables | Multi-source tables (parent + child) | +| Extends `ISourceCache`/`ISourceList`, returns void | Single table, framed as "produced" | +| Produces non-changeset output (`IObservable`, `bool`, etc.) | Single table, framed as subscription lifecycle | +| Is a class, interface, enum, or non-extension member | Summary, params, returns, remarks (no event table) | + +### 3. Apply Quality Rules + +**Params**: Every `` links its type via ``. Exempt: `bool`, `int`, `string`. + +**SeeAlso**: Bidirectional for overload sets. Link safe/async/immutable variants, similar operators, complementary operators, commonly confused operators. + +**Type references**: Types use ``. Method/event/property names use `...`. Internal types must not appear; describe behavior instead. + +**Tone**: No em dashes. No emoji. No filler words (comprehensive, robust, seamlessly, leverage, utilize, facilitate). Be specific: "an **Update** is emitted" not "the change is propagated". Use "Worth noting" for non-obvious behavior. + ### 4. Verify ```bash dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framework net9.0 ``` -- 0 errors, no new CS1574 warnings (unresolved cref) +- 0 errors, no new CS1574 warnings - No em dashes (Unicode 0x2014) - No "The source." remaining -- All tables use `Event` -- Spot-check 3-5 operators against their implementation -- Diff against main: confirm no existing useful information was lost +- Spot-check 3-5 operators against implementation +- Diff against main: confirm nothing lost -## Before and After Example +## Before and After -**BEFORE** (typical old-style doc): +**BEFORE** (old-style): ```xml /// /// Filters the specified source. /// -/// The type of the object. -/// The type of the key. /// The source. /// The filter. /// An observable which emits change sets. @@ -169,56 +158,43 @@ dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framew /// Filters items from the source changeset stream using a static predicate. /// Only items satisfying are included downstream. /// -/// The type of items in the cache. -/// The type of the key. -/// The source of to filter. +/// The source of . /// A predicate. Items returning true are included. -/// A changeset stream containing only items that satisfy . +/// A changeset stream containing only items satisfying . /// /// Use this overload when the predicate is fixed for the subscription's lifetime. /// /// EventBehavior /// AddPredicate evaluated. If passes, Add emitted. Otherwise dropped. -/// UpdateRe-evaluated. Both pass: Update. New passes, old didn't: Add. Old passed, new doesn't: Remove. Neither: dropped. +/// UpdateRe-evaluated. Both pass: Update. New passes only: Add. Old passed only: Remove. Neither: dropped. /// RemoveIf downstream, Remove emitted. Otherwise dropped. -/// RefreshRe-evaluated. Now passes but didn't: Add. Still passes: Refresh forwarded. No longer passes: Remove. Still fails: dropped. +/// RefreshRe-evaluated. Now passes: Add. Still passes: Refresh. No longer passes: Remove. Still fails: dropped. /// OnErrorForwarded. /// OnCompletedForwarded. /// -/// Worth noting: Refresh events trigger re-evaluation, which can promote or demote items. +/// Worth noting: Refresh re-evaluation can promote or demote items. /// /// /// /// ``` -## Tone Rules - -- No em dashes. Use colons, commas, parentheses. -- No emoji. -- No filler: "comprehensive", "robust", "seamlessly", "leverage", "utilize", "facilitate". -- Be specific: "an **Update** is emitted" not "the change is propagated". -- Use "Worth noting" for non-obvious behavior (not "Gotchas"). -- Write like a senior developer, not a marketing brochure. - ## Batch Application -For large-scale passes across many operators: - -1. Dispatch parallel **read-only** agents to analyze implementations (group by family: Transform, Filter, Merge, etc.) -2. Apply edits via a **single agent or yourself** (multiple agents editing one file will clobber each other's work) -3. Build, audit metrics (table count, seealso count, em dashes, old params), spot-check accuracy +1. Dispatch parallel **read-only** agents to analyze implementations (group by family) +2. Apply edits via **single agent or yourself** (multiple agents editing one file clobber each other) +3. Build, audit metrics, spot-check accuracy 4. Diff against main for lost details ## Common Mistakes | Mistake | Fix | |---------|-----| -| Guessing behavior from method name | Read the implementation file | +| Guessing behavior from method name | Read the implementation | | `IComparer` for a type | `` | -| Referencing internal types in public docs | Describe behavior instead | -| One-way seealso links | Make them bidirectional | +| Referencing internal types | Describe behavior instead | +| One-way seealso links | Bidirectional | | Multiple agents editing same file | One editor at a time | -| Removing existing useful information | Additive only; diff against main | -| Tables with only cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear too | -| Params missing type links | Every param mentions and links its type | \ No newline at end of file +| Removing existing information | Additive only; diff against main | +| Only cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear | +| Params missing type links | Every param links its type | \ No newline at end of file From 6df341ed632dc6a40515fbfa4eecd1c38ef25a48 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:14:33 -0700 Subject: [PATCH 10/23] docs: distinguish delegating vs independent overloads in skill Not all secondary overloads delegate to a primary. When an overload has a different implementation or different behavior, it needs its own full documentation, not just inheritdoc. --- .github/skills/add-documentation/SKILL.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md index 028f29ac4..674651987 100644 --- a/.github/skills/add-documentation/SKILL.md +++ b/.github/skills/add-documentation/SKILL.md @@ -87,11 +87,16 @@ Start from this template for any primary overload. Delete sections that do not a /// ``` -For **secondary overloads** that delegate to a primary: +For **secondary overloads** in an overload set: ```xml + /// /// A that [specific difference]. /// This overload [what differs]. Delegates to . + + + + ``` ## Process From 28538b34804c49f0ea7b1e79a6f7f434f0e1d2c8 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:16:57 -0700 Subject: [PATCH 11/23] Revert "docs: add type links to all param descriptions in cache operators" This reverts commit 13241c058d58b55e590a9b9129108b5ba46ff8a1. --- .../Cache/ObservableCacheEx.SortAndBind.cs | 219 +- .../ObservableCacheEx.VirtualiseAndPage.cs | 195 +- src/DynamicData/Cache/ObservableCacheEx.cs | 5167 +++++++++-------- 3 files changed, 3014 insertions(+), 2567 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index 68e0edb9a..7cb3afb04 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -18,9 +18,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. + /// The source changeset stream. + /// The resulting read only observable collection. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -38,10 +39,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// The Bind and sort default options. + /// The source changeset stream. + /// The resulting read only observable collection. + /// Bind and sort default options. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -60,9 +62,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. + /// The source changeset stream. + /// The list to bind to. /// An observable which will emit change sets. + /// This is the primary Bind overload for paged data. It applies paged changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -75,10 +78,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. - /// The Bind and sort default options. + /// The source changeset stream. + /// The list to bind to. + /// Bind and sort default options. /// An observable which will emit change sets. + /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -92,9 +96,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. + /// The source changeset stream. + /// The resulting read only observable collection. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -112,10 +117,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// The Bind and sort default options. + /// The source changeset stream. + /// The resulting read only observable collection. + /// Bind and sort default options. /// An observable which will emit change sets. + /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -134,9 +140,10 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. + /// The source changeset stream. + /// The list to bind to. /// An observable which will emit change sets. + /// This is the primary Bind overload for virtualized data. It applies virtualized changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList) @@ -149,10 +156,11 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. - /// The Bind and sort default options. + /// The source changeset stream. + /// The list to bind to. + /// Bind and sort default options. /// An observable which will emit change sets. + /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable>> source, IList targetList, @@ -161,14 +169,8 @@ public static partial class ObservableCacheEx where TKey : notnull => new BindVirtualized(source, targetList, options).Run(); - /// - /// Bind sorted data to the specified collection, for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The list to bind to. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList) @@ -176,15 +178,8 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified collection, for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The list to bind to. - /// The Bind and sort default options. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -193,15 +188,7 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(targetList, Comparer.Default, options); - /// - /// Bind sorted data to the specified collection. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The list to bind to. - /// An comparer to order the resulting dataset. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -211,15 +198,34 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparer, DynamicDataOptions.SortAndBind); /// - /// Bind sorted data to the specified collection. + /// Sorts the source changeset using and applies incremental changes + /// directly to , keeping it sorted in-place. + /// Combines the behavior of Sort and Bind into a single optimized step. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. - /// An comparer to order the resulting dataset. - /// The Bind and sort default options. + /// The source changeset stream. + /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. + /// The comparer to order the resulting dataset. + /// Bind and sort options controlling reset threshold and initial capacity. /// An observable which will emit change sets. + /// + /// + /// This operator is the preferred replacement for the .Sort().Bind() chain. + /// It applies sort logic and collection mutations in a single pass, avoiding intermediate allocations. + /// + /// + /// EventBehavior + /// AddItem inserted at the correct sorted position in . + /// UpdateOld item removed and new item inserted at its sorted position. + /// RemoveItem removed from . + /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Large batches may trigger a full list reset (clear + re-add) instead of incremental moves, controlled by . This fires CollectionChanged with Reset action, which can be more efficient for UI virtualization but causes a visual flicker. + /// + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -229,15 +235,7 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparer, options, targetList).Run(); - /// - /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The list to bind to. - /// An of which enables the sort order to be changed.> - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -247,15 +245,33 @@ public static partial class ObservableCacheEx source.SortAndBind(targetList, comparerChanged, DynamicDataOptions.SortAndBind); /// - /// Bind sorted data to the specified collection, using an observable of comparers to switch sort order. + /// Sorts the source changeset and applies incremental changes directly to , + /// re-sorting when the comparer observable emits a new comparer. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The list to bind to. - /// An of which enables the sort order to be changed.> - /// The Bind and sort default options. + /// The source changeset stream. + /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. + /// An observable of comparers which enables the sort order to be changed. + /// Bind and sort options controlling reset threshold and initial capacity. /// An observable which will emit change sets. + /// + /// + /// When emits a new comparer, all items are re-sorted and the target list is updated. + /// No data is emitted until the first comparer arrives. + /// + /// + /// EventBehavior + /// AddItem inserted at the correct sorted position in . + /// UpdateOld item removed and new item inserted at its sorted position. + /// RemoveItem removed from . + /// RefreshSort position is re-evaluated. If the position changed, the item is moved in-place. + /// Comparer changedFull re-sort of all items. The target list is updated to reflect the new order. + /// OnErrorForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until the comparer observable produces its first value. Large batches or comparer changes may trigger a full list reset depending on . + /// + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, IList targetList, @@ -265,14 +281,8 @@ public static partial class ObservableCacheEx where TKey : notnull => new SortAndBind(source, comparerChanged, options, targetList).Run(); - /// - /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection) @@ -280,15 +290,8 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection for an object which implements IComparable>. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// The Bind and sort default options. - /// An observable which will emit change sets. + /// + /// This overload uses for types implementing . public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -297,15 +300,7 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, Comparer.Default, options); - /// - /// Bind sorted data to the specified readonly observable collection. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// An comparer to order the resulting dataset. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -314,16 +309,11 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparer, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// An comparer to order the resulting dataset. - /// The Bind and sort default options. - /// An observable which will emit change sets. + /// + /// The source changeset stream. + /// The resulting read only observable collection. + /// The comparer to order the resulting dataset. + /// Bind and sort options controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -342,15 +332,7 @@ public static partial class ObservableCacheEx return new SortAndBind(source, comparer, options, observableCollection).Run(); } - /// - /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// An of which enables the sort order to be changed. - /// An observable which will emit change sets. + /// public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -359,16 +341,11 @@ public static partial class ObservableCacheEx where TKey : notnull => source.SortAndBind(out readOnlyObservableCollection, comparerChanged, DynamicDataOptions.SortAndBind); - /// - /// Bind sorted data to the specified readonly observable collection, using an observable of comparers to switch sort order. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// An of which enables the sort order to be changed.> - /// The Bind and sort default options. - /// An observable which will emit change sets. + /// + /// The source changeset stream. + /// The resulting read only observable collection. + /// An observable of comparers which enables the sort order to be changed. + /// Bind and sort options controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index e6e30ecef..325fe8e4e 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -12,16 +12,8 @@ namespace DynamicData; /// public static partial class ObservableCacheEx { - /// - /// Sort and virtualize the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An comparer to order the resulting dataset. - /// An of that specifies the virtualizing parameters. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndVirtualize(this IObservable> source, IComparer comparer, IObservable virtualRequests) @@ -29,16 +21,8 @@ public static IObservable>> So where TKey : notnull => source.SortAndVirtualize(comparer, virtualRequests, new SortAndVirtualizeOptions()); - /// - /// Sort and virtualize the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed.> - /// An of that specifies the virtualizing parameters. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -53,16 +37,35 @@ public static IObservable>> So } /// - /// Sort and virtualize the underlying data from the specified source. + /// Sorts unsorted data using , then returns only items within the + /// virtual window defined by . /// /// The type of the object. /// The type of the key. - /// The source of . - /// An comparer to order the resulting dataset. - /// An of that specifies the virtualizing parameters. - /// The Addition optimization options for virtualization. + /// The source changeset stream. + /// The comparer to order the resulting dataset. + /// The virtualizing requests (start index and page size). + /// Additional optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. + /// + /// + /// Combines sorting and index-based windowing. Only items within the current virtual window are emitted. + /// Use the observable comparer overload if you need to change sort order at runtime. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. + /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. + /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. + /// RefreshSort position is re-evaluated. Window membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until produces its first value. Changing the window can cause a full recalculation of visible items. + /// + /// + /// public static IObservable>> SortAndVirtualize( this IObservable> source, IComparer comparer, @@ -78,16 +81,35 @@ public static IObservable>> So } /// - /// Sort and virtualize the underlying data from the specified source. + /// Sorts unsorted data, then returns only the items within the virtual window defined by + /// (start index + size). Re-sorts when the comparer observable emits. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed.> - /// An of that specifies the virtualizing parameters. - /// The Addition optimization options for virtualization. + /// The source changeset stream. + /// An observable of comparers which enables the sort order to be changed. + /// The virtualizing requests (start index and page size). + /// Additional optimization options for virtualization. /// An observable which will emit virtual change sets. /// source. + /// + /// + /// Combines sorting and index-based windowing in a single operator. Only items within the + /// current virtual window are emitted downstream. The window is defined by a start index and size. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls within the window, an Add is emitted. Items pushed out of the window produce a Remove. + /// UpdateIf the updated item is within the window, an Update is emitted. Sort position changes may cause items to enter or leave the window. + /// RemoveIf the removed item was within the window, a Remove is emitted. Items shifted into the window produce an Add. + /// RefreshSort position is re-evaluated. Window membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until both the comparer observable and virtualRequests have produced their first values. Changing the window or comparer can cause a full recalculation of visible items. + /// + /// + /// public static IObservable>> SortAndVirtualize( this IObservable> source, IObservable> comparerChanged, @@ -107,8 +129,8 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of that specifies the virtualizing parameters. + /// The source changeset stream. + /// The virtualising requests. /// An observable which will emit virtual change sets. /// source. [Obsolete(Constants.VirtualizeIsObsolete)] @@ -123,16 +145,25 @@ public static IObservable> Virtualise - /// Limits the size of the result set to the specified number, ordering by the comparer. + /// Returns the top items from the source, sorted by . + /// Equivalent to SortAndVirtualize with a fixed window starting at index 0. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An comparer. - /// The size. + /// The source changeset stream. + /// The comparer. + /// The maximum number of items to return. /// An observable which will emit virtual change sets. /// source. /// size;Size should be greater than zero. + /// + /// + /// Internally delegates to + /// with a fixed of (0, size). + /// + /// Worth noting: When the Nth item is displaced by a new item with higher sort priority, the displaced item is emitted as a Remove and the new item as an Add. + /// + /// public static IObservable>> Top(this IObservable> source, IComparer comparer, int size) where TObject : notnull where TKey : notnull @@ -153,7 +184,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source changeset stream. /// The size. /// An observable which will emit virtual change sets. /// source. @@ -173,16 +204,8 @@ public static IObservable> Top(t return new Virtualise(source, Observable.Return(new VirtualRequest(0, size))).Run(); } - /// - /// Sort and page the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An comparer to order the resulting dataset. - /// An of that specifies the paging parameters. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndPage(this IObservable> source, IComparer comparer, IObservable pageRequests) @@ -190,16 +213,8 @@ public static IObservable>> SortA where TKey : notnull => source.SortAndPage(comparer, pageRequests, new SortAndPageOptions()); - /// - /// Sort and page the underlying data from the specified source. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed.> - /// An of that specifies the paging parameters. - /// An observable which will emit virtual change sets. - /// source. + /// + /// This overload uses default . public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -214,16 +229,34 @@ public static IObservable>> SortA } /// - /// Sort and page the underlying data from the specified source. + /// Sorts unsorted data using , then pages the result using + /// . /// /// The type of the object. /// The type of the key. - /// The source of . - /// An comparer to order the resulting dataset. - /// An of that specifies the paging parameters. - /// The Addition optimization options for virtualization. - /// An observable which will emit virtual change sets. + /// The source changeset stream. + /// The comparer to order the resulting dataset. + /// The page requests (page number and page size). + /// Additional optimization options for paging. + /// An observable which will emit paged change sets. /// source. + /// + /// + /// Combines sorting and page-based windowing. Only items on the current page are emitted. + /// Use the observable comparer overload if you need to change sort order at runtime. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. + /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. + /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. + /// RefreshSort position is re-evaluated. Page membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until produces its first value. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. + /// + /// public static IObservable>> SortAndPage( this IObservable> source, IComparer comparer, @@ -239,16 +272,34 @@ public static IObservable>> SortA } /// - /// Sort and page the underlying data from the specified source. + /// Sorts unsorted data, then pages the result using page number and page size from + /// . Re-sorts when the comparer observable emits. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed.> - /// An of that specifies the paging parameters. - /// The Addition optimization options for virtualization. - /// An observable which will emit virtual change sets. + /// The source changeset stream. + /// An observable of comparers which enables the sort order to be changed. + /// The page requests (page number and page size). + /// Additional optimization options for paging. + /// An observable which will emit paged change sets. /// source. + /// + /// + /// Combines sorting and page-based windowing in a single operator. Only items on the current page + /// are emitted downstream. The page is defined by a 1-based page number and page size. + /// + /// + /// EventBehavior + /// AddIf the new item's sorted position falls on the current page, an Add is emitted. Items pushed off the page produce a Remove. + /// UpdateIf the updated item is on the current page, an Update is emitted. Sort position changes may move items on or off the page. + /// RemoveIf the removed item was on the current page, a Remove is emitted. Items shifted onto the page produce an Add. + /// RefreshSort position is re-evaluated. Page membership may change. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No data is emitted until both the comparer observable and pageRequests have produced their first values. Page numbers are 1-based. Requesting a page beyond the data range results in an empty page. + /// + /// public static IObservable>> SortAndPage( this IObservable> source, IObservable> comparerChanged, @@ -268,8 +319,8 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of that specifies the paging parameters. + /// The source changeset stream. + /// The page requests. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] public static IObservable> Page(this IObservable> source, IObservable pageRequests) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 016ccceec..119cb44aa 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. +// Copyright (c) 2011-2025 Roland Pheasant. All rights reserved. // Roland Pheasant licenses this file to you under the MIT license. // See the LICENSE file in the project root for full license information. @@ -28,18 +28,32 @@ public static partial class ObservableCacheEx private const bool DefaultResortOnSourceRefresh = true; /// - /// Inject side effects into the stream using the specified adaptor. + /// Injects a side effect into the changeset stream by calling . + /// for every changeset, then forwarding it downstream unchanged. /// - /// The type of the object. + /// The type of items in the cache. /// The type of the key. - /// The source of . - /// The adaptor. - /// An observable which will emit change sets. - /// - /// source - /// or - /// destination. - /// + /// The source changeset stream. + /// The adaptor whose Adapt method is called for each changeset. + /// An observable that emits the same changesets as , after the adaptor has processed each one. + /// + /// + /// This is a thin wrapper around Rx's Do operator. The adaptor receives each changeset + /// as a side effect; the changeset itself is forwarded downstream unmodified. + /// + /// + /// EventBehavior + /// AddPassed to the adaptor, then forwarded. + /// UpdatePassed to the adaptor, then forwarded. + /// RemovePassed to the adaptor, then forwarded. + /// RefreshPassed to the adaptor, then forwarded. + /// OnErrorForwarded to the downstream observer. The adaptor is not called. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. + /// + /// public static IObservable> Adapt(this IObservable> source, IChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -50,19 +64,10 @@ public static IObservable> Adapt(this I return source.Do(adaptor.Adapt); } - /// - /// Inject side effects into the stream using the specified sorted adaptor. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The adaptor. - /// An observable which will emit change sets. - /// - /// source - /// or - /// destination. - /// + /// + /// The source sorted changeset stream. + /// The sorted adaptor whose Adapt method is called for each sorted changeset. + /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) where TObject : notnull where TKey : notnull @@ -74,13 +79,28 @@ public static IObservable> Adapt(this I } /// - /// Adds or updates the cache with the specified item. + /// Adds or updates the cache with the specified item, producing a changeset with a single Add + /// (if the key is new) or Update (if the key already exists). /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to add or update. + /// + /// Convenience method that wraps a single-item mutation inside . + /// + /// EventBehavior + /// AddProduced when the key does not already exist in the cache. + /// UpdateProduced when the key already exists. The previous value is included in the changeset. + /// RemoveNot produced by this method. + /// RefreshNot produced by this method. + /// OnErrorNot applicable (synchronous mutation). + /// OnCompletedNot applicable (synchronous mutation). + /// + /// + /// is null. + /// + /// public static void AddOrUpdate(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -90,15 +110,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item)); } - /// - /// Adds or updates the cache with the specified item. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The item. - /// An equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache. + /// The item to add or update. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -108,16 +124,10 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(item, equalityComparer)); } - /// - /// - /// Adds or updates the cache with the specified items. - /// - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An items. - /// source. + /// + /// The source cache. + /// The items to add or update. + /// Batch overload. All items are added/updated inside a single call, producing one changeset. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -127,17 +137,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items)); } - /// - /// - /// Adds or updates the cache with the specified items. - /// - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An items. - /// An equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache. + /// The items to add or update. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -147,15 +151,11 @@ public static void AddOrUpdate(this ISourceCache s source.Edit(updater => updater.AddOrUpdate(items, equalityComparer)); } - /// - /// Adds or updates the cache with the specified item / key pair. - /// - /// The type of the object. - /// The type of the key. - /// The source cache. + /// + /// The source intermediate cache. /// The item to add or update. - /// The key to add or update. - /// source. + /// The key to associate with the item. + /// This overload operates on , which requires an explicit key parameter. public static void AddOrUpdate(this IIntermediateCache source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -172,8 +172,8 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// The source of . - /// The other of streams. + /// The source changeset stream. + /// The others. /// An observable which emits change sets. /// source or others. public static IObservable> And(this IObservable> source, params IObservable>[] others) @@ -192,7 +192,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// An of of streams. source. + /// The source collection of changeset streams. /// An observable which emits change sets. /// /// source @@ -214,7 +214,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// An of of streams. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -231,7 +231,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -248,7 +248,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -260,13 +260,14 @@ public static IObservable> And(this IOb } /// - /// Converts the source to an read only observable cache. + /// Wraps an in a read-only facade, hiding the mutable API. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable cache. - /// source. + /// The source cache to wrap. + /// A read-only . + /// is null. + /// public static IObservableCache AsObservableCache(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -277,14 +278,24 @@ public static IObservableCache AsObservableCache(t } /// - /// Converts the source to a readonly observable cache. + /// Materializes a changeset stream into a queryable, read-only . + /// The cache subscribes to the source on first access and maintains a live snapshot of all items. /// /// The type of the object. /// The type of the key. - /// The source of . - /// if set to true all methods are synchronised. There is no need to apply locking when the consumer can be sure the read / write operations are already synchronised. - /// An observable cache. - /// source. + /// The source changeset stream. + /// If true (default), all cache operations are synchronized. Set to false when the caller guarantees single-threaded access. + /// A read-only observable cache that reflects the current state of the pipeline. + /// + /// + /// Disposing the returned cache unsubscribes from the source stream. The cache's Connect() + /// method provides a changeset stream of its own, which re-emits the current state on each new subscriber. + /// + /// When is false, a is used internally. + /// + /// is null. + /// + /// public static IObservableCache AsObservableCache(this IObservable> source, bool applyLocking = true) where TObject : notnull where TKey : notnull @@ -302,34 +313,48 @@ public static IObservableCache AsObservableCache(t #if SUPPORTS_ASYNC_DISPOSABLE /// /// - /// Automatically disposes items within the source collection, upon removal of the collection or teardown of the operator. + /// Disposes items implementing or when they are removed or replaced, + /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. /// /// - /// Individual items are disposed after removal or replacement changes have been sent downstream. - /// All items previously-published on the stream are disposed after the stream finalizes. - /// This includes both upstream completion or failure, or downstream un-subscription. - /// - /// - /// Disposal is supported for both and items. - /// Items implementing neither of these interfaces are unaffected by this operator. + /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators + /// see the removal before disposal occurs. Items implementing neither disposal interface are ignored. /// /// - /// The type of items in the source collection. - /// The type of key values used to uniquely identify items in the source collection. - /// The source of . + /// The type of items in the cache. + /// The type of the key. + /// The source changeset stream. /// /// - /// An to be invoked upon each subscription to this operator, allowing the consumer access to the "disposalsCompleted" stream for that subscription. + /// Invoked once per subscription, providing an that signals when all + /// calls have finished. The signal emits a single value + /// and then completes. /// /// - /// The "disposalsCompleted" stream allows the consumer to properly observe the asynchronous disposal of any items that are disposed by the operator. This stream will emit a single value, and then complete, upon successfull completion of all invocations performed by the operator. + /// This is delivered on a separate channel from the main changeset stream so it can be observed even + /// if the source stream errors. /// + /// + /// A stream that forwards all changesets from unchanged. + /// /// - /// Providing these notifications within a downstream channel separate from the main collection change stream ensures that these notifications can be observed even in the event of a failure within the operator, or within stream. + /// Change reason handling: + /// + /// EventBehavior + /// AddTracks the item. No disposal. + /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. + /// RemoveDisposes the removed item. + /// RefreshPassed through. No disposal. + /// /// - /// - /// A stream containing copies of all changes observed from . - /// Throws for and . + /// + /// On stream completion, error, or subscription disposal, all items still in the cache are disposed. + /// items are disposed synchronously; items + /// are dispatched via the signal. + /// + /// + /// or is null. + /// public static IObservable> AsyncDisposeMany( this IObservable> source, Action> disposalsCompletedAccessor) @@ -345,10 +370,10 @@ public static IObservable> AsyncDisposeMany /// The object of the change set. /// The key of the change set. - /// The source of . Observable. - /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// A When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// The source observable. + /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -376,11 +401,11 @@ public static IObservable> AutoRefresh( /// The object of the change set. /// The key of the change set. /// The type of the property. - /// The source of . Observable. - /// An Specify a property to observe changes. When it changes a Refresh is invoked. - /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// A When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// The source observable. + /// Specify a property to observe changes. When it changes a Refresh is invoked. + /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, Expression> propertyAccessor, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -408,10 +433,10 @@ public static IObservable> AutoRefreshThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source of . Observable change set. - /// A observable which acts on items within the collection and produces a value when the item should be refreshed. - /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// The source observable change set. + /// An observable which acts on items within the collection and produces a value when the item should be refreshed. + /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull @@ -423,11 +448,14 @@ public static IObservable> AutoRefreshOnObservableThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source of . Observable change set. - /// A observable which acts on items within the collection and produces a value when the item should be refreshed. - /// A Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// The source observable change set. + /// An observable which acts on items within the collection and produces a value when the item should be refreshed. + /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The scheduler. /// An observable change set with additional refresh changes. + /// + /// Worth noting: Per-item observable errors are silently ignored (not forwarded to the downstream observer). Only source stream errors propagate. + /// public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -439,17 +467,34 @@ public static IObservable> AutoRefreshOnObservable - /// Batches the updates for the specified time period. + /// Collects changesets emitted within a time window and merges them into a single changeset. + /// Uses Rx's Buffer operator followed by . /// /// The type of the object. /// The type of the key. - /// The source of . - /// A time span. - /// The scheduler. - /// An observable which emits change sets. - /// source - /// or - /// scheduler. + /// The source changeset stream. + /// The time window for batching. + /// The scheduler for timing. Defaults to . + /// An observable that emits merged changesets, one per time window. + /// + /// + /// All changesets received during the time window are concatenated into a single changeset. + /// This is useful for reducing UI update frequency when the source emits many rapid changes. + /// + /// + /// EventBehavior + /// AddBuffered and included in the merged changeset at the end of the time window. + /// UpdateBuffered and included in the merged changeset. + /// RemoveBuffered and included in the merged changeset. + /// RefreshBuffered and included in the merged changeset. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedAny remaining buffered changes are flushed, then completion is forwarded. + /// + /// Worth noting: The merged changeset may contain contradictory changes (e.g., Add then Remove for the same key). Downstream operators handle this correctly, but raw inspection of the changeset may be surprising. + /// + /// is null. + /// + /// public static IObservable> Batch(this IObservable> source, TimeSpan timeSpan, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -459,66 +504,55 @@ public static IObservable> Batch(this I return source.Buffer(timeSpan, scheduler ?? GlobalConfig.DefaultScheduler).FlattenBufferResult(); } - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload delegates to the primary overload with initialPauseState: false. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, scheduler); - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload delegates to the primary overload with default initialPauseState: false. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, scheduler: scheduler).Run(); - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// A Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// This overload omits initialPauseState (defaults to false) but accepts a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, timeOut, scheduler); /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. + /// Conditionally buffers changesets while a pause signal is active, then flushes all buffered + /// changes as a single merged changeset when the signal resumes. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// A Specify a time to ensure the buffer window does not stay open for too long. On completion buffering will cease. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// The source changeset stream. + /// When true, buffering begins. When false, the buffer is flushed. + /// If true, starts in a paused (buffering) state. + /// Maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. + /// The scheduler for timeout timing. + /// An observable that emits changesets, buffered or passthrough depending on pause state. + /// + /// + /// While paused, incoming changesets are accumulated. On resume (or timeout), all buffered changesets + /// are merged into a single changeset and emitted. While not paused, changesets pass through immediately. + /// + /// + /// EventBehavior + /// AddBuffered while paused; forwarded immediately while active. + /// UpdateBuffered while paused; forwarded immediately while active. + /// RemoveBuffered while paused; forwarded immediately while active. + /// RefreshBuffered while paused; forwarded immediately while active. + /// OnErrorForwarded to the downstream observer. Buffered data is lost. + /// OnCompletedForwarded. Any remaining buffered data is flushed before completion. + /// + /// Worth noting: If the source completes while paused, buffered data IS flushed before OnCompleted. However, if the source errors while paused, buffered data is lost. + /// + /// or is null. + /// + /// public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -529,19 +563,13 @@ public static IObservable> BatchIf(this return new BatchIf(source, pauseIfTrueSelector, timeOut, initialPauseState, scheduler: scheduler).Run(); } - /// - /// Batches the underlying updates if a pause signal (i.e when the buffer selector return true) has been received. - /// When a resume signal has been received the batched updates will be fired. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of bool. When true, observable begins to buffer and when false, window closes and buffered result if notified. - /// if set to true [initial pause state]. - /// An of Specify a time observable. The buffer will be emptied each time the timer produces a value and when it completes. On completion buffering will cease. - /// The scheduler. - /// An observable which emits change sets. - /// source. + /// + /// The source changeset stream. + /// When true, buffering begins. When false, the buffer is flushed. + /// If true, starts in a paused (buffering) state. + /// An observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. + /// The scheduler. + /// This overload accepts an explicit timer observable instead of a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IObservable? timer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, timer, scheduler).Run(); @@ -551,8 +579,8 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. + /// The source changeset stream. + /// The destination. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. /// source. @@ -578,9 +606,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. - /// The binding options. + /// The source changeset stream. + /// The destination. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -597,9 +625,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. - /// The updater. + /// The source changeset stream. + /// The destination. + /// The updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, IObservableCollectionAdaptor updater) @@ -628,9 +656,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// The binding options. + /// The source changeset stream. + /// The resulting read only observable collection. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -649,11 +677,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. + /// The source changeset stream. + /// The resulting read only observable collection. /// The number of changes before a reset notification is triggered. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// The Specify an adaptor to change the algorithm to update the target collection. + /// Specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, IObservableCollectionAdaptor? adaptor = null) @@ -685,8 +713,8 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. + /// The source changeset stream. + /// The destination. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination) @@ -704,9 +732,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. - /// The binding options. + /// The source changeset stream. + /// The destination. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -725,9 +753,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. - /// The updater. + /// The source changeset stream. + /// The destination. + /// The updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, ISortedObservableCollectionAdaptor updater) @@ -756,9 +784,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. - /// The binding options. + /// The source changeset stream. + /// The resulting read only observable collection. + /// The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -779,11 +807,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . - /// The resulting read only observable collection. + /// The source changeset stream. + /// The resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// The Specify an adaptor to change the algorithm to update the target collection. + /// Specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, ISortedObservableCollectionAdaptor? adaptor = null) @@ -813,8 +841,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source of . - /// The target binding list. + /// The source changeset stream. + /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -837,8 +865,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source of . - /// The target binding list. + /// The source changeset stream. + /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -859,14 +887,24 @@ public static IObservable> Bind(this IO #endif /// - /// Buffers changes for an initial period only. After the period has elapsed, not further buffering occurs. + /// Buffers the initial burst of changesets for the specified duration, merges them into a single + /// changeset, then passes all subsequent changesets through without buffering. /// /// The object type. /// The type of the key. - /// The source of . Change set. - /// A period to buffer, measure from the time that the first item arrives. - /// The scheduler to buffer on. - /// An observable which emits change sets. + /// The source change set. + /// The time window to buffer, measured from when the first changeset arrives. + /// The scheduler for timing. Defaults to . + /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. + /// + /// + /// Useful for aggregating the initial snapshot (which may arrive as many small changesets) into a + /// single changeset for efficient downstream processing, while leaving subsequent live updates untouched. + /// + /// Internally uses , Rx Buffer, and . + /// + /// + /// public static IObservable> BufferInitial(this IObservable> source, TimeSpan initialBuffer, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => source.DeferUntilLoaded().Publish( @@ -878,15 +916,28 @@ public static IObservable> BufferInitial - /// Cast the object to the specified type. - /// Alas, I had to add the converter due to type inference issues. + /// Casts each item in the changeset to a new type using the provided converter function. + /// Equivalent to + /// but named for discoverability when a simple type cast or conversion is needed. /// - /// The type of the object. + /// The type of the source object. /// The type of the key. - /// The type of the destination. - /// The source of . - /// A conversion factory. - /// An observable which emits change sets. + /// The type of the destination object. + /// The source changeset stream. + /// The conversion function applied to each item. + /// An observable changeset of converted items. + /// + /// + /// EventBehavior + /// AddCalls and emits an Add with the converted item. + /// UpdateCalls on the new value and emits an Update. + /// RemoveEmits a Remove. The converter is not called. + /// RefreshForwarded as Refresh. The converter is not called. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// public static IObservable> Cast(this IObservable> source, Func converter) where TSource : notnull where TKey : notnull @@ -898,14 +949,27 @@ public static IObservable> Cast - /// Changes the primary key. + /// Re-keys each item in the changeset by applying to the current item. + /// The original change reason is preserved; only the key is remapped. /// /// The type of the object. /// The type of the source key. /// The type of the destination key. - /// The source of . - /// A key selector eg. (item) => newKey. - /// An observable which emits change sets. + /// The source changeset stream. + /// A function that computes the destination key from the item, e.g. (item) => item.NewId. + /// An observable changeset with items re-keyed using . + /// + /// + /// EventBehavior + /// Add is called on the item. An Add is emitted with the destination key. + /// Update is called on the current item. An Update is emitted with the destination key. If the key selector produces a different destination key for the updated value than it did for the original value, downstream consumers will see an Update for a key that may not match the original Add. + /// Remove is called on the item. A Remove is emitted with the destination key. + /// Refresh is called on the item. A Refresh is emitted with the destination key. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -922,16 +986,11 @@ public static IObservable> ChangeKey - /// Changes the primary key. - /// - /// The type of the object. - /// The type of the source key. - /// The type of the destination key. - /// The source of . - /// A key selector eg. (key, item) => newKey. - /// An observable which emits change sets. - /// source. + /// + /// + /// This overload also provides the source key to , + /// allowing the destination key to be derived from both the item and its original key. + /// public static IObservable> ChangeKey(this IObservable> source, Func keySelector) where TObject : notnull where TSourceKey : notnull @@ -949,12 +1008,23 @@ public static IObservable> ChangeKey - /// Clears all data. + /// Removes all items from the cache, producing a changeset with a Remove for every item. /// /// The type of the object. /// The type of the key. - /// The source. - /// source. + /// The source cache to clear. + /// + /// + /// EventBehavior + /// AddNot produced by this operation. + /// UpdateNot produced by this operation. + /// RemoveA Remove is emitted for every item currently in the cache. + /// RefreshNot produced by this operation. + /// OnErrorNot applicable (synchronous mutation method). + /// OnCompletedNot applicable (synchronous mutation method). + /// + /// + /// is null. public static void Clear(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -964,13 +1034,7 @@ public static void Clear(this ISourceCache source) source.Edit(updater => updater.Clear()); } - /// - /// Clears all items from the cache. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// source. + /// public static void Clear(this IIntermediateCache source) where TObject : notnull where TKey : notnull @@ -980,13 +1044,7 @@ public static void Clear(this IIntermediateCache s source.Edit(updater => updater.Clear()); } - /// - /// Clears all data. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// source. + /// public static void Clear(this LockFreeObservableCache source) where TObject : notnull where TKey : notnull @@ -996,13 +1054,25 @@ public static void Clear(this LockFreeObservableCache - /// Clones the changes into the specified collection. + /// Applies each change from the source changeset to the specified collection as a side effect. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The target. - /// An observable which emits change sets. + /// The source changeset stream. + /// The target collection to which changes are applied. + /// An observable that forwards all changesets from unchanged. + /// + /// + /// EventBehavior + /// AddThe item is added to . Forwarded as Add. + /// UpdateThe previous item is removed from and the current item is added. Forwarded as Update. + /// RemoveThe item is removed from . Forwarded as Remove. + /// RefreshIgnored ( has no concept of refresh). Forwarded as Refresh. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// public static IObservable> Clone(this IObservable> source, ICollection target) where TObject : notnull where TKey : notnull @@ -1041,14 +1111,13 @@ public static IObservable> Clone(this I } /// - /// Convert the object using the specified conversion function. - /// This is a lighter equivalent of Transform and is designed to be used with non-disposable objects. + /// Obsolete: use instead. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source of . - /// A conversion factory. + /// The source changeset stream. + /// The conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] public static IObservable> Convert(this IObservable> source, Func conversionFactory) @@ -1068,12 +1137,26 @@ public static IObservable> Convert - /// Defer the subscription until the stream has been inflated with data. + /// Suppresses all emissions until the first non-empty changeset arrives, then replays that changeset and all subsequent ones. + /// If the source never produces a non-empty changeset, the stream waits indefinitely. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits change sets. + /// The source changeset stream. + /// An observable that begins emitting changesets once the first non-empty changeset is received. + /// + /// + /// EventBehavior + /// AddForwarded as Add once the initial non-empty changeset has been received. + /// UpdateForwarded as Update once loaded. + /// RemoveForwarded as Remove once loaded. + /// RefreshForwarded as Refresh once loaded. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Blocks indefinitely if the cache or stream never receives any data. Ensure the source will eventually emit at least one changeset. + /// + /// public static IObservable> DeferUntilLoaded(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1083,13 +1166,7 @@ public static IObservable> DeferUntilLoaded(source).Run(); } - /// - /// Defer the subscription until the stream has been inflated with data. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An observable which emits change sets. + /// public static IObservable> DeferUntilLoaded(this IObservableCache source) where TObject : notnull where TKey : notnull @@ -1100,17 +1177,39 @@ public static IObservable> DeferUntilLoaded - /// Disposes each item when no longer required. /// - /// Individual items are disposed after removal or replacement changes have been sent downstream. - /// All items previously-published on the stream are disposed after the stream finalizes. + /// Disposes items implementing when they are removed or replaced, + /// and disposes all tracked items when the stream completes, errors, or the subscription is disposed. + /// + /// + /// Individual items are disposed after the changeset has been forwarded downstream, so downstream operators + /// see the removal before disposal occurs. Items that do not implement are ignored. /// /// /// The type of the object. /// The type of the key. - /// The source of . - /// A continuation of the original stream. - /// source. + /// The source changeset stream. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddTracks the item. No disposal. + /// UpdateDisposes the previous value (if it differs by reference from the current). Tracks the new value. + /// RemoveDisposes the removed item. + /// RefreshPassed through. No disposal. + /// + /// + /// + /// On stream completion, error, or subscription disposal, all remaining tracked items are disposed. + /// All disposal is synchronous via . + /// For items that implement , use instead. + /// + /// + /// is null. + /// + /// public static IObservable> DisposeMany(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1126,11 +1225,12 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source of . - /// A value selector. + /// The source changeset stream. + /// The value selector. /// An observable which will emit distinct change sets. /// /// Due to it's nature only adds or removes can be returned. + /// Worth noting: Reference counting assumes value equality is transitive. Mutable value objects with inconsistent Equals implementations can corrupt ref counts. /// /// source. public static IObservable> DistinctValues(this IObservable> source, Func valueSelector) @@ -1144,16 +1244,14 @@ public static IObservable> DistinctValues>(observer => new DistinctCalculator(source, valueSelector).Run().SubscribeSafe(observer)); } - /// - /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items - /// in the list and amends only the differences. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An items to add, update or delete. - /// An equality comparer used to determine whether a new item is the same as an existing cached item. - /// source. + /// + /// The source cache to diff against. + /// The complete snapshot of items to diff against the cache. + /// An used to determine whether a new item is the same as an existing cached item. + /// + /// This overload uses an instead of a delegate + /// to determine item equality. + /// public static void EditDiff(this ISourceCache source, IEnumerable allItems, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -1166,15 +1264,26 @@ public static void EditDiff(this ISourceCache sour } /// - /// Loads the cache with the specified items in an optimised manner i.e. calculates the differences between the old and new items - /// in the list and amends only the differences. + /// Diffs a complete snapshot of items against the current cache contents, producing the minimal set of + /// Add, Update, and Remove changes needed to bring the cache in sync with the snapshot. /// /// The type of the object. /// The type of the key. - /// The source. - /// An items to compare and add, update or delete. - /// A Expression to determine whether an item's value is equal to the old value (current, previous) => current.Version == previous.Version. - /// source. + /// The source cache to diff against. + /// The complete snapshot of desired items. + /// A function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// + /// + /// EventBehavior + /// AddItems in whose key is not in the cache produce an Add. + /// UpdateItems present in both and the cache that differ (per ) produce an Update. + /// RemoveItems in the cache whose key is not in produce a Remove. + /// RefreshNot produced by this operation. + /// OnErrorNot applicable (synchronous mutation method). + /// OnCompletedNot applicable (synchronous mutation method). + /// + /// + /// , , or is null. public static void EditDiff(this ISourceCache source, IEnumerable allItems, Func areItemsEqual) where TObject : notnull where TKey : notnull @@ -1188,15 +1297,29 @@ public static void EditDiff(this ISourceCache sour } /// - /// Converts an Observable of Enumerable to an Observable ChangeSet that updates when the enumerables changes. Counterpart operator to . + /// Converts an of into a changeset stream by diffing each + /// emission against the previous one. Each emission replaces the entire dataset. + /// Counterpart to . /// /// The type of the object. /// The type of the key. - /// An of source. - /// A Key Selection Function for the ChangeSet. - /// Optional instance to use for comparing values. - /// An observable cache. - /// source. + /// The source observable of item snapshots. + /// A function to extract the unique key from each item. + /// Optional for comparing items. Uses default equality if null. + /// An observable changeset representing the incremental differences between successive snapshots. + /// + /// + /// EventBehavior + /// AddItems in the new snapshot whose key was not in the previous snapshot produce an Add. + /// UpdateItems present in both snapshots that differ (per ) produce an Update. + /// RemoveItems in the previous snapshot whose key is absent from the new snapshot produce a Remove. + /// RefreshNot produced by this operator. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. + /// public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1208,15 +1331,27 @@ public static IObservable> EditDiff(thi } /// - /// Converts an Observable Optional to an Observable ChangeSet that adds/removes/updates as the optional changes. + /// Converts an of into a changeset stream that tracks + /// a single item: Some produces an Add or Update, and None produces a Remove. /// /// The type of the object. /// The type of the key. - /// An source. - /// A Key Selection Function for the ChangeSet. - /// Optional instance to use for comparing values. - /// An observable changeset. - /// source. + /// The source observable of optional values. + /// A function to extract the unique key from each item. + /// Optional for comparing items. Uses default equality if null. + /// An observable changeset tracking the single optional item. + /// + /// + /// EventBehavior + /// AddEmitted when the source produces Some(value) and no item was previously tracked. + /// UpdateEmitted when the source produces Some(value) and an item was already tracked with a different value (per ). + /// RemoveEmitted when the source produces None and an item was previously tracked. + /// RefreshNot produced by this operator. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// or is null. public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1228,12 +1363,24 @@ public static IObservable> EditDiff(thi } /// - /// Ensures there are no duplicated keys in the observable changeset. + /// Validates that each changeset contains no duplicate keys. + /// If duplicates are detected, an is emitted via OnError. /// - /// The source of . Change set. /// The type of the object. /// The type of the key. - /// A changeset which guarantees a key is only present at most once in the changeset. + /// The source changeset stream to validate. + /// A changeset stream guaranteed to contain unique keys per changeset. + /// + /// + /// EventBehavior + /// AddForwarded as Add if the key is unique within the changeset. + /// UpdateForwarded as Update if the key is unique within the changeset. + /// RemoveForwarded as Remove if the key is unique within the changeset. + /// RefreshForwarded as Refresh if the key is unique within the changeset. + /// OnErrorForwarded. Also emitted with if duplicate keys are detected in a changeset. + /// OnCompletedForwarded to the downstream observer. + /// + /// public static IObservable> EnsureUniqueKeys(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1249,8 +1396,8 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// The source of . - /// The other of streams. + /// The source changeset stream. + /// The others. /// An observable which emits change sets. /// /// source @@ -1277,7 +1424,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// An of of streams. sources. + /// The sources. /// An observable which emits change sets. /// /// source @@ -1299,7 +1446,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// An of of streams. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1316,7 +1463,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1333,7 +1480,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1345,19 +1492,28 @@ public static IObservable> Except(this } /// - /// Automatically removes items from the stream after the time specified by - /// the timeSelector elapses. Return null if the item should never be removed. + /// Schedules automatic removal of items after the timeout returned by . + /// If returns null, the item never expires. /// /// The type of the object. /// The type of the key. - /// The source of . - /// A time selector. - /// An observable which emits change sets. - /// - /// source - /// or - /// timeSelector. - /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// An observable changeset that includes timer-driven Remove changes for expired items. + /// + /// When a timer fires, a Remove is emitted for the expired item. + /// + /// EventBehavior + /// AddSchedules a removal timer based on . Forwarded as Add. + /// UpdateResets the removal timer for the item. Forwarded as Update. + /// RemoveCancels the removal timer. Forwarded as Remove. + /// RefreshForwarded as Refresh. No timer change. + /// OnErrorForwarded. All pending timers are cancelled. + /// OnCompletedForwarded. All pending timers are cancelled. + /// + /// Worth noting: A null return from means "never expire". Update changes reset the expiration timer. + /// + /// or is null. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector) @@ -1367,21 +1523,10 @@ public static IObservable> ExpireAfter( source: source, timeSelector: timeSelector); - /// - /// Automatically removes items from the stream after the time specified by - /// the timeSelector elapses. Return null if the item should never be removed. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// A time selector. - /// The scheduler. - /// An observable which emits change sets. - /// - /// source - /// or - /// timeSelector. - /// + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// The scheduler used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1393,21 +1538,15 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, scheduler: scheduler); - /// - /// Automatically removes items from the stream on the next poll after the time specified by - /// the time selector elapses. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// A time selector. Return null if the item should never be removed. - /// A polling interval. If this value is specified, items are expired on an interval. - /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. - /// - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// This is less accurate but more efficient when many items share similar expiration times. + /// + /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next + /// poll after their timeout elapses, which trades accuracy for reduced timer overhead. + /// public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1419,22 +1558,11 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector, pollingInterval: pollingInterval); - /// - /// Automatically removes items from the stream on the next poll after the time specified by - /// the time selector elapses. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// A time selector. Return null if the item should never be removed. - /// A polling interval. If this value is specified, items are expired on an interval. - /// This will result in a loss of accuracy of the time which the item is expired but is less computationally expensive. - /// - /// The scheduler. - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// + /// The source changeset stream. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// The scheduler used to schedule polling and expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1449,21 +1577,22 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// Automatically removes items from the cache after the time specified by - /// the time selector elapses. + /// Automatically removes items from the after the timeout returned + /// by . Returns an observable of the removed key-value pairs (not a changeset stream). /// /// The type of the object. /// The type of the key. - /// The cache. - /// A time selector. Return null if the item should never be removed. - /// A polling interval. Since multiple timer subscriptions can be expensive, - /// it may be worth setting the interval. - /// - /// The scheduler. - /// An observable of enumerable of the key values which has been removed. - /// source - /// or - /// timeSelector. + /// The source cache from which expired items are removed. + /// A function returning the expiration timeout for each item, or null for no expiration. + /// If specified, items are expired on a polling interval rather than per-item timers. + /// The scheduler used to schedule expiration timers. Defaults to if null. + /// An observable that emits the key-value pairs of items removed from the cache by expiration. + /// + /// Unlike the stream-based overloads, this operates directly on the + /// and returns the removed items as collections, + /// not as a changeset stream. + /// + /// or is null. public static IObservable>> ExpireAfter( this ISourceCache source, Func timeSelector, @@ -1478,14 +1607,29 @@ public static IObservable>> ExpireAfter< scheduler: scheduler); /// - /// Filters the specified source. + /// Filters items from the source changeset stream using a static predicate. + /// Only items that satisfy are included downstream. /// /// The type of the object. /// The type of the key. - /// The source of . - /// A filter. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// The source changeset stream. + /// The predicate used to determine whether each item is included. + /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets, which can be useful for monitoring loading status. + /// An observable changeset containing only items that satisfy . + /// + /// + /// EventBehavior + /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. + /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshThe predicate is re-evaluated. If the item now passes but previously did not, an Add is emitted. If it still passes, a Refresh is forwarded. If it no longer passes, a Remove is emitted. If it still fails, the change is dropped. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: Refresh events trigger re-evaluation, which can promote or demote items. Pair with for property-change-driven filtering. + /// + /// + /// public static IObservable> Filter( this IObservable> source, Func filter, @@ -1497,15 +1641,11 @@ public static IObservable> Filter( filter: filter, suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// Creates a filtered stream which can be dynamically filtered. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of . Observable to change the underlying predicate. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// + /// + /// This overload does not accept a reapplyFilter signal. It is equivalent to calling the + /// full dynamic overload with as the reapply observable. + /// public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1518,19 +1658,34 @@ public static IObservable> Filter( suppressEmptyChangeSets: suppressEmptyChangeSets); /// - /// Creates a filtered stream which can be dynamically filtered, based on state values passed through to a static filtering predicate. + /// Creates a dynamically filtered stream where the filter predicate depends on external state. + /// Each emission from triggers a full re-filtering of all items. /// /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source of . - /// An stream of state values to be passed to . - /// A static predicate to be used to determine which items should be included or excluded by the filter. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. - /// Throws for , , and . + /// The source changeset stream. + /// A stream of state values to be passed to . + /// A predicate that receives the current state and an item, returning true to include or false to exclude. + /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets. + /// An observable changeset containing only items satisfying for the latest state. + /// , , or is null. /// - /// Usually, should emit an initial value, immediately upon subscription. This is because cannot be invoked until the first state value is received, and accordingly, the operator will treat all items as excluded until then. Each value emitted by will trigger a full re-filtering of the entire collection. + /// + /// should emit an initial value immediately upon subscription. + /// Until the first state value arrives, no items pass the filter (all items are excluded). + /// Each subsequent state emission triggers a full re-evaluation of every item in the collection. + /// + /// + /// EventBehavior + /// AddEvaluated against the current state. If it passes, an Add is emitted. Otherwise dropped. + /// UpdateRe-evaluated. Four outcomes as with the static overload. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshRe-evaluated against the current state. May produce Add, Refresh, Remove, or be dropped. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: should emit an initial value immediately. Each emission triggers a full re-evaluation of all items, which can be expensive for large collections. /// public static IObservable> Filter( this IObservable> source, @@ -1546,16 +1701,17 @@ public static IObservable> Filter(), suppressEmptyChangeSets: suppressEmptyChangeSets); - /// - /// Creates a filtered stream which can be dynamically filtered. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An of . Observable to change the underlying predicate. - /// An of Observable to re-evaluate whether the filter still matches items. Use when filtering on mutable values. - /// By default empty changeset notifications are suppressed for performance reasons. Set to false to publish empty changesets. Doing so can be useful for monitoring loading status. - /// An observable which emits change sets. + /// + /// The source changeset stream. + /// An observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. + /// An observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. + /// When true (default), empty changesets are suppressed for performance. + /// + /// In addition to the per-item behavior described in the static overload, + /// emissions from replace the predicate and trigger full re-filtering, + /// while emissions from re-evaluate all items against the current predicate. + /// Worth noting: No items are included until the predicate observable emits its first value. + /// public static IObservable> Filter( this IObservable> source, IObservable> predicateChanged, @@ -1576,8 +1732,8 @@ public static IObservable> Filter( /// /// The type of collection items to be filtered. /// The type of the key values of each collection item. - /// The source of . Stream of collection items to be filtered. - /// A filtering predicate to be applied to each item. + /// The source stream of collection items to be filtered. + /// The filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. /// @@ -1591,6 +1747,15 @@ public static IObservable> Filter( /// Your filtering predicate runs quickly, and does not heavily allocate memory /// /// Note that, because filtering is purely deterministic, Refresh operations are transparently ignored by this operator. + /// + /// EventBehavior + /// AddThe predicate is evaluated. If it passes, an Add is emitted. Otherwise the item is dropped. + /// UpdateFour outcomes: if both old and new values pass, an Update is emitted. If only the new value passes, an Add is emitted. If only the old value passed, a Remove is emitted. If neither passes, the change is dropped. + /// RemoveIf the item was included downstream, a Remove is emitted. Otherwise dropped. + /// RefreshDropped. Because items are assumed immutable, there is nothing to re-evaluate. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// /// public static IObservable> FilterImmutable( this IObservable> source, @@ -1610,16 +1775,48 @@ public static IObservable> FilterImmutable - /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. + /// Filters items using a per-item that controls inclusion. + /// Each item's observable is created by and toggles the item in or out of the downstream stream. /// /// The type of the object. /// The type of the key. - /// The source of . - /// A Factory function used to create the observable bool that controls whether that given item passes the filter or not. - /// A Optional time to buffer changes from the observable bools. - /// The Optional scheduler to use when buffering the changes. - /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. - /// One of the given parameters was null. + /// The source changeset stream. + /// A factory that creates an for each item and its key. When the observable emits true, the item is included; when false, it is excluded. + /// Optional time window to buffer inclusion changes from per-item observables before re-evaluating. + /// Optional scheduler used for buffering. + /// An observable changeset containing only items whose per-item observable most recently emitted true. + /// + /// + /// Source changeset handling (parent events): + /// + /// + /// EventBehavior + /// AddSubscribes to the per-item observable. The item is not included downstream until the observable emits its first true. + /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. Inclusion state is reset; the new observable must emit before the item reappears. + /// RemoveDisposes the item's observable subscription. If the item was included downstream, a Remove is emitted. + /// RefreshForwarded as Refresh if the item is currently included downstream. Otherwise dropped. + /// + /// + /// Per-item observable handling (filter observable events): + /// + /// + /// EmissionBehavior + /// First trueThe item is included: an Add is emitted downstream. + /// false (was included)The item is excluded: a Remove is emitted downstream. + /// true (was excluded)The item is re-included: an Add is emitted downstream. + /// true (was included)No effect (already included). + /// false (was excluded)No effect (already excluded). + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains in its current inclusion state. No further toggling is possible for this item. + /// + /// + /// Worth noting: Items are invisible downstream until their per-item observable emits at least one true. + /// If an item's observable never emits, the item never appears. The parameter batches + /// rapid inclusion changes from per-item observables into a single re-evaluation, reducing changeset chatter. + /// + /// + /// or is null. + /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1630,17 +1827,10 @@ public static IObservable> FilterOnObservable(source, filterFactory, buffer, scheduler).Run(); } - /// - /// Filters the stream of changes according to an Observable bool that is created for each item using the specified factory function. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// A Factory function used to create the observable bool that controls whether that given item passes the filter or not. - /// A Optional time to buffer changes from the observable bools. - /// The Optional scheduler to use when buffering the changes. - /// An observable changeset that only contains items whose corresponding observable bool has emitted true as its most recent value. - /// One of the given parameters was null. + /// + /// + /// This overload does not provide the key to ; only the item is passed. + /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1652,13 +1842,12 @@ public static IObservable> FilterOnObservable - /// Ensure that finally is always called. Thanks to Lee Campbell for this. + /// Obsolete: do not use. This can cause unhandled exception issues. Use the standard Rx Finally operator instead. /// /// The type contained within the observables. - /// An source. - /// An finally action. + /// The source changeset stream. + /// The finally action. /// An observable which has always a finally action applied. - /// source. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) { @@ -1669,13 +1858,15 @@ public static IObservable FinallySafe(this IObservable source, Action f } /// - /// Flattens an update collection to it's individual items. + /// Unwraps each into individual + /// values via . /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits change set values on a flatten result. - /// source. + /// The source changeset stream. + /// An observable of individual values. + /// is null. + /// public static IObservable> Flatten(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1686,12 +1877,14 @@ public static IObservable> Flatten(this IOb } /// - /// Convert the result of a buffer operation to a single change set. + /// Merges a list of changesets (typically from an Rx Buffer operation) into a single changeset + /// by concatenating all changes. Empty buffers are filtered out. /// /// The type of the object. /// The type of the key. - /// An source. - /// An observable which emits change sets. + /// The source observable of buffered changeset lists. + /// An observable changeset combining all changes from each buffer into a single emission. + /// is null. public static IObservable> FlattenBufferResult(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -1702,13 +1895,29 @@ public static IObservable> FlattenBufferResult - /// Provides a call back for each change. + /// Invokes for every individual in each changeset, + /// regardless of change reason. The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An action. - /// An observable which will perform the action on each item. + /// The source changeset stream. + /// The action to invoke for each change. Receives the full struct, including , , , and . + /// A stream that forwards all changesets from unchanged. + /// + /// + /// All change reasons (Add, Update, Remove, Refresh) trigger the callback. + /// Use , + /// , + /// , or + /// + /// to target a specific reason. + /// + /// + /// Implemented via Rx's Do operator on the changeset stream. + /// Exceptions thrown in propagate as OnError to the subscriber. No try-catch is applied. + /// + /// + /// or is null. public static IObservable> ForEachChange(this IObservable> source, Action> action) where TObject : notnull where TKey : notnull @@ -1719,20 +1928,12 @@ public static IObservable> ForEachChange changes.ForEach(action)); } - /// - /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. - /// This is the equivalent of SQL full join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1749,19 +1950,48 @@ public static IObservable> FullJoin - /// Joins the left and right observable data sources, taking any left or right values and matching them, provided that the left or the right has a value. - /// This is the equivalent of SQL full join. + /// Joins two changeset streams, producing a result for every key that appears on either side (or both). + /// Both sides are because a given key may only exist on one side at any point. + /// Equivalent to SQL FULL OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddEmits with the left value and the matching right (or Optional.None if no right exists). + /// UpdateRe-invokes with the new left value and current right (if any). + /// RemoveIf a right match still exists, re-invokes the selector with left as Optional.None. If neither side remains, removes the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddEmits with the matching left (or Optional.None) and the right value. + /// UpdateRe-invokes selector with current left (if any) and the new right value. + /// RemoveIf a left match still exists, re-invokes the selector with right as Optional.None. If neither side remains, removes the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1777,20 +2007,12 @@ public static IObservable> FullJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. - /// This is the equivalent of SQL full join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1807,19 +2029,49 @@ public static IObservable> FullJoinMany - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left or the right has a value. - /// This is the equivalent of SQL full join. + /// Groups right-side items by their mapped key, then full-joins each group to the left source. + /// A result is produced for every key that appears on either side (or both). The left value is + /// because only the right side may have entries for a given key. + /// Equivalent to SQL FULL OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddEmits with the left value and the current right group for that key (may be empty). + /// UpdateRe-invokes with the new left value and current right group. + /// RemoveIf the right group is non-empty, re-invokes with left as Optional.None. If both sides are empty, removes the result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group, then re-invokes selector with the current left (if any) and the updated group. + /// UpdateUpdates the right group and re-invokes selector. + /// RemoveUpdates the right group. If the group becomes empty and no left exists, removes the result. Otherwise re-invokes selector. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -1836,16 +2088,16 @@ public static IObservable> FullJoinMany - /// Groups the source on the value returned by group selector factory. - /// A group is included for each item in the resulting group source. + /// Groups items from the source changeset, producing groups only for group keys present in . + /// Useful for parent-child relationships where parents and children come from different streams. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A group selector factory. + /// The source changeset stream. + /// The group selector factory. /// - /// An of used to determine the result groups. + /// A distinct stream used to determine the result. /// /// /// Useful for parent-child collection when the parent and child are soured from different streams. @@ -1864,14 +2116,38 @@ public static IObservable> Group - /// Groups the source on the value returned by group selector factory. + /// Groups items from the source changeset by a key extracted via . + /// Each group is an observable sub-cache that receives changes for its members. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A group selector key. - /// An observable which will emit group change sets. + /// The source changeset stream. + /// Extracts the group key from each item. + /// An observable that emits group changesets. Each group exposes a sub-cache of its members. + /// + /// + /// Items are assigned to groups based on the value returned by . + /// Groups are created on demand when the first item is assigned, and removed when their last member is removed. + /// + /// + /// EventBehavior + /// AddThe group key is evaluated. The item is added to the corresponding group (creating the group if new). An Add is emitted to the group's sub-cache. + /// UpdateThe group key is re-evaluated. If unchanged, an Update is emitted within the same group. If the key changed, the item is removed from the old group (emitting Remove) and added to the new group (emitting Add). An empty old group is removed. + /// RemoveThe item is removed from its group. If the group becomes empty, the group itself is removed from the output. + /// RefreshThe group key is re-evaluated. If unchanged, a Refresh is forwarded within the group. If the key changed, the item moves between groups (Remove from old, Add to new). + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// Worth noting: Each group is a live sub-cache that can be subscribed to independently. Subscribers + /// to a group receive only changes for items in that group. When a group is removed (becomes empty), + /// its sub-cache completes. + /// + /// + /// + /// + /// public static IObservable> Group(this IObservable> source, Func groupSelectorKey) where TObject : notnull where TKey : notnull @@ -1883,23 +2159,12 @@ public static IObservable> Group(source, groupSelectorKey, null).Run(); } - /// - /// Groups the source on the value returned by group selector factory. - /// - /// The type of the object. - /// The type of the key. - /// The type of the group key. - /// The source of . - /// A group selector key. - /// An of Invoke to the for the grouping to be re-evaluated. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// + /// The source changeset stream. + /// Extracts the group key from each item. + /// When this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. + /// An observable that emits group changesets. + /// This overload adds a signal. When it fires, every item in the cache is re-grouped using the current selector, which is useful when the grouping depends on mutable item state. public static IObservable> Group(this IObservable> source, Func groupSelectorKey, IObservable regrouper) where TObject : notnull where TKey : notnull @@ -1913,22 +2178,34 @@ public static IObservable> Group - /// Groups the source on the value returned by the latest value from the group selector factory observable. + /// Groups items using a dynamically changing group selector function. + /// Each time emits a new selector, all items are re-grouped. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// An of . group selector key observable. - /// An of Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// The source changeset stream. + /// An observable that emits group selector functions. Each emission triggers a full re-grouping of all items. + /// Optional signal to force re-evaluation of all items against the current selector. + /// An observable that emits group changesets. + /// + /// + /// Unlike the static-selector overload, this accepts an observable of selector functions. When a new selector + /// arrives, every item is re-evaluated and may move between groups. The optional + /// signal triggers re-evaluation without changing the selector (useful when item properties that affect grouping change). + /// + /// + /// EventBehavior + /// AddThe current selector determines the group. Item is added to the group (group created if new). + /// UpdateGroup key re-evaluated. Item may move between groups if the key changed. + /// RemoveItem removed from its group. Empty groups are removed. + /// RefreshGroup key re-evaluated. Item may move between groups. + /// OnErrorForwarded from source or from . + /// OnCompletedForwarded when the source completes. + /// + /// + /// + /// public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -1940,23 +2217,11 @@ public static IObservable> Group(source, groupSelectorKeyObservable, regrouper).Run(); } - /// - /// Groups the source on the value returned by the latest value from the group selector factory observable. - /// - /// The type of the object. - /// The type of the key. - /// The type of the group key. - /// The source of . - /// An of . group selector key observable. - /// An of Fires when the current Grouping Selector needs to re-evaluate all the items in the cache. - /// An observable which will emit group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// + /// The source changeset stream. + /// An observable of selector functions that take only the item (not the key). + /// Optional signal to force re-evaluation. + /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -1968,14 +2233,52 @@ public static IObservable> Group - /// Groups the source by the latest value from their observable created by the given factory. + /// Groups items where each item's group key is determined by a per-item observable. + /// The observable is created by for each item. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A group selector key. - /// An observable which will emit group change sets. + /// The source changeset stream. + /// Factory that creates a group key observable for each item and its key. + /// An observable that emits group changesets. Each group is a live sub-cache of its members. + /// + /// + /// Unlike which evaluates + /// the group key synchronously, this operator defers group assignment until the per-item observable emits. + /// + /// + /// Source changeset handling (parent events): + /// + /// + /// EventBehavior + /// AddSubscribes to the per-item group key observable. The item is not placed in any group until the observable emits its first group key. + /// UpdateDisposes the old item's group key subscription and subscribes to the new item's observable. The item is removed from its current group until the new observable emits. + /// RemoveDisposes the item's group key subscription. The item is removed from its current group. Empty groups are removed. + /// RefreshNo effect on subscriptions. The item remains in its current group. + /// + /// + /// Per-item observable handling (group key observable events): + /// + /// + /// EmissionBehavior + /// First valueThe item is placed into the group matching the emitted key. An Add appears in that group's sub-cache. If the group is new, the group itself is added to the output. + /// New value (different key)The item moves: Remove from the old group, Add to the new group. If the old group becomes empty, it is removed from the output. + /// Same value (unchanged key)No effect (filtered by DistinctUntilChanged). + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains in its current group. No further group key changes are possible for this item. + /// + /// + /// Worth noting: Items are invisible (not in any group) until their per-item observable emits at least one + /// group key. If an item's observable never emits, the item never appears in any group. Per-item observable errors + /// terminate the entire stream. The output completes when the source completes and all per-item observables have + /// also completed. + /// + /// + /// + /// + /// + /// public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull where TKey : notnull @@ -1993,8 +2296,8 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A group selector key. + /// The source changeset stream. + /// The group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull @@ -2013,10 +2316,10 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// An property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// The source changeset stream. + /// The property selector used to group the items. + /// A time span that indicates the throttle to wait for property change events. + /// The scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnProperty(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2036,10 +2339,10 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// An property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// The source changeset stream. + /// The property selector used to group the items. + /// A time span that indicates the throttle to wait for property change events. + /// The scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnPropertyWithImmutableState(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2053,22 +2356,35 @@ public static IObservable> Gr } /// - /// Groups the source on the value returned by group selector factory. Each update produces immutable grouping. + /// Groups items by , emitting immutable group snapshots instead of mutable sub-caches. + /// Each group change contains a frozen copy of the group's state at that point in time. /// /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A group selector key. - /// An of Invoke to the for the grouping to be re-evaluated. - /// An observable which will emit immutable group change sets. - /// - /// source - /// or - /// groupSelectorKey - /// or - /// groupController. - /// + /// The source changeset stream. + /// Extracts the group key from each item. + /// Optional signal to force re-evaluation of all items against the group selector. + /// An observable that emits immutable group changesets. + /// + /// + /// Behaves identically to + /// in terms of how items are assigned to groups, but each group emission is an immutable snapshot. + /// This makes it safe for parallel processing and eliminates race conditions on group state. + /// The tradeoff is higher memory usage, since each change produces a new snapshot of the affected group. + /// + /// + /// EventBehavior + /// AddItem added to its group. An immutable snapshot of the group is emitted. + /// UpdateIf group key unchanged, group snapshot re-emitted. If changed, item moves between groups; both affected groups emit new snapshots. + /// RemoveItem removed from group. Updated snapshot emitted. Empty groups are removed. + /// RefreshGroup key re-evaluated. If changed, item moves; affected group snapshots emitted. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// + /// + /// public static IObservable> GroupWithImmutableState(this IObservable> source, Func groupSelectorKey, IObservable? regrouper = null) where TObject : notnull where TKey : notnull @@ -2085,7 +2401,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// The source of . Observable which emits change sets. + /// The source observable which emits change sets. /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2097,8 +2413,8 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// The source of . - /// A ignore function (current,previous)=>{ return true to ignore }. + /// The source changeset stream. + /// The ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) where TObject : notnull @@ -2124,8 +2440,8 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// The source of . - /// A include function (current,previous)=>{ return true to include }. + /// The source changeset stream. + /// The include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) where TObject : notnull @@ -2142,20 +2458,12 @@ public static IObservable> IncludeUpdateWhen - /// Joins the left and right observable data sources, taking values when both left and right values are present - /// This is the equivalent of SQL inner join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left and right values into a destination object. The composite key is not provided in this overload. + /// Overload that omits the composite key from the result selector. Delegates to . public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2172,19 +2480,48 @@ public static IObservable> IncludeUpdateWhen - /// Groups the right data source and joins the to the left and the right sources, taking values when both left and right values are present - /// This is the equivalent of SQL inner join. + /// Joins two changeset streams, producing a result only for keys that exist on both sides simultaneously. + /// When either side loses its value for a key, the joined result is removed. Equivalent to SQL INNER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). + /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a matching right value exists, invokes and emits an Add. If no right match, no emission. + /// UpdateIf a matching right exists, re-invokes the selector and emits an Update. + /// RemoveRemoves all joined results involving the removed left key. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddIf a matching left value exists, invokes the selector and emits an Add. + /// UpdateIf a matching left exists, re-invokes the selector and emits an Update. + /// RemoveRemoves the joined result for this right key (if it was downstream). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// The output is keyed by a (TLeftKey, TRightKey) composite tuple, since a single left item may match multiple right items. + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func<(TLeftKey leftKey, TRightKey rightKey), TLeft, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2200,20 +2537,12 @@ public static IObservable> IncludeUpdateWhen(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. - /// This is the equivalent of SQL inner join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2230,19 +2559,48 @@ public static IObservable> InnerJoinMany - /// Groups the right data source and joins the resulting group to the left data source, matching these using the specified key selector. Results are included when the left and right have matching values. - /// This is the equivalent of SQL inner join. + /// Groups right-side items by their mapped key, then inner-joins each group to the left source. + /// A result is produced only when a left item and at least one right item share the same key. + /// Equivalent to SQL INNER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a non-empty right group exists for this key, invokes and emits an Add. Otherwise no emission. + /// UpdateIf a right group exists, re-invokes the selector and emits an Update. + /// RemoveRemoves the joined result (if it was downstream). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If a matching left exists and the group was previously empty, emits an Add. If already joined, emits an Update. + /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. + /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2259,29 +2617,34 @@ public static IObservable> InnerJoinMany - /// Invokes Refresh method for an object which implements IEvaluateAware. + /// Calls Evaluate() on items that implement when a Refresh change arrives. + /// Other change reasons are forwarded without invoking Evaluate. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits change sets. + /// The source changeset stream. + /// An observable that emits the same changesets as , unchanged. + /// + /// + /// EventBehavior + /// AddForwarded unchanged. + /// UpdateForwarded unchanged. + /// RemoveForwarded unchanged. + /// RefreshCalls Evaluate() on the item, then forwards the change. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// public static IObservable> InvokeEvaluate(this IObservable> source) where TObject : IEvaluateAware where TKey : notnull => source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); - /// - /// Joins the left and right observable data sources, taking all left values and combining any matching right values. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the optional right into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2298,18 +2661,48 @@ public static IObservable> LeftJoin - /// Joins the left and right observable data sources, taking all left values and combining any matching right values. + /// Joins two changeset streams, producing a result for every left-side key. The right side is + /// because a matching right item may or may not exist. All left items + /// appear in the output regardless. Equivalent to SQL LEFT OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the left value and matching right (or Optional.None). + /// UpdateRe-invokes the selector with the new left value and current right (if any). + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddIf a matching left exists, re-invokes the selector (right transitions from None to Some) and emits an Update. + /// UpdateIf a matching left exists, re-invokes the selector with the new right value. + /// RemoveIf a matching left exists, re-invokes the selector (right transitions from Some to None) and emits an Update. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2325,20 +2718,12 @@ public static IObservable> LeftJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. - /// This is the equivalent of SQL left join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2355,19 +2740,48 @@ public static IObservable> LeftJoinMany - /// Groups the right data source and joins the two sources matching them using the specified key selector, taking all left values and combining any matching right values. - /// This is the equivalent of SQL left join. + /// Groups right-side items by their mapped key, then left-joins each group to the left source. + /// A result is produced for every left-side key. The right group may be empty if no right items match. + /// Equivalent to SQL LEFT OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the left value and the current right group (which may be empty). + /// UpdateRe-invokes the selector with the new left value and current right group. + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If a matching left exists, re-invokes the selector and emits an Update. + /// UpdateUpdates the right group and re-invokes the selector if a matching left exists. + /// RemoveUpdates the right group. If a matching left exists, re-invokes the selector (group may now be empty). + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -2384,16 +2798,27 @@ public static IObservable> LeftJoinMany - /// Applies a size limiter to the number of records which can be included in the - /// underlying cache. When the size limit is reached the oldest items are removed. + /// Applies a FIFO size limit to the changeset stream. When the number of items exceeds , + /// the oldest items are evicted and emitted as Remove changes. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The size. - /// An observable which emits change sets. - /// source. - /// size cannot be zero. + /// The source changeset stream. + /// The maximum number of items allowed. Must be greater than zero. + /// An observable changeset stream with size-limited contents. + /// + /// + /// EventBehavior + /// AddForwarded. If the cache exceeds the size limit, the oldest items are emitted as Remove changes. + /// UpdateForwarded unchanged. + /// RemoveForwarded unchanged. + /// RefreshForwarded unchanged. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// + /// is null. + /// is zero or negative. public static IObservable> LimitSizeTo(this IObservable> source, int size) where TObject : notnull where TKey : notnull @@ -2409,17 +2834,17 @@ public static IObservable> LimitSizeTo( } /// - /// Limits the number of records in the cache to the size specified. When the size is reached - /// the oldest items are removed from the cache. + /// Operates directly on a , removing the oldest items when the cache + /// exceeds . Returns an observable of the evicted key-value pairs (not a changeset stream). /// /// The type of the object. /// The type of the key. - /// The source. - /// The size limit. - /// The scheduler. - /// An observable which emits the key value pairs. - /// source. - /// Size limit must be greater than zero. + /// The source cache to apply the size limit to. + /// The maximum number of items allowed. Must be greater than zero. + /// Optional scheduler for observing changes. Defaults to . + /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. + /// is null. + /// is zero or negative. public static IObservable>> LimitSizeTo(this ISourceCache source, int sizeLimit, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -2454,18 +2879,38 @@ public static IObservable>> LimitSizeTo< } /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. + /// Subscribes to a child observable for each item in the source cache changeset stream and merges all child + /// emissions into a single . When an item is added, + /// creates its child subscription. When updated, the previous child subscription is disposed and a new one is created. + /// When removed, its child subscription is disposed. Refresh changes have no effect on subscriptions. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . - /// A observable selector. - /// An observable which emits the transformed value. - /// source - /// or - /// observableSelector. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of values emitted by child observables. + /// The source cache changeset stream. + /// Factory function that produces a child observable for each source item. + /// An observable that emits values from all active child observables, interleaved by arrival order. + /// + /// + /// This operator does not produce changesets. It produces a flat stream of + /// values, similar to Rx SelectMany but lifecycle-aware: child subscriptions track items entering and + /// leaving the source cache. + /// + /// + /// EventBehavior + /// AddCalls to create a child observable and subscribes to it. Emissions from the child flow into the merged output. + /// UpdateDisposes the previous child subscription and creates a new one for the updated item. + /// RemoveDisposes the child subscription for the removed item. + /// RefreshNo effect on subscriptions. The child observable continues unchanged. + /// OnErrorErrors from child observables are silently swallowed (the child is unsubscribed). Errors from the source changeset stream terminate the merged output. + /// OnCompletedThe output completes only when the source completes and all active child observables have also completed. + /// + /// Worth noting: The output is a plain , not a changeset stream. If you need merged changesets, use instead. + /// + /// or is null. + /// + /// + /// public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2476,19 +2921,9 @@ public static IObservable MergeMany(t return new MergeMany(source, observableSelector).Run(); } - /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . - /// A observable selector. - /// An observable which emits the transformed value. - /// source - /// or - /// observableSelector. + /// + /// The source cache changeset stream. + /// Factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2500,13 +2935,52 @@ public static IObservable MergeMany(t } /// - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges multiple changeset streams that arrive dynamically into a single unified changeset stream. + /// Each inner stream emitted by the outer observable is subscribed and its changes forwarded downstream. + /// When multiple sources provide the same key, the first source to add it retains priority unless a + /// comparer-based overload is used. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// A unified changeset stream containing changes from all active source streams. + /// + /// + /// Each inner changeset stream is independently tracked in its own cache. When multiple sources provide the same key, + /// this overload uses first-in-wins semantics: the value from whichever source added the key first is + /// the one published downstream. To control which value wins for duplicate keys, use an overload that + /// accepts an , which selects the lowest-ordered value across all sources. + /// An can be provided separately to suppress no-op updates when + /// the new value equals the currently published value for a key. + /// + /// + /// Overload families: MergeChangeSets has 16 overloads organized along three axes: + /// (1) Source type: dynamic (IObservable<IObservable<IChangeSet>>, sources arrive at runtime), + /// pair (source + other, exactly two streams), or static (, all sources known up front). + /// (2) Conflict resolution: none (first-in-wins), (lowest-ordered wins), + /// (suppresses duplicate updates), or both. + /// (3) Completion: static overloads accept a completable flag; when false, the output never completes + /// even after all sources finish (useful for "live" merge scenarios). + /// + /// + /// EventBehavior + /// AddIf no source has previously provided this key, an Add is emitted downstream. If another source already holds this key, the new value is tracked internally but not emitted (first-in-wins). With a comparer, the lowest-ordered value across all sources is selected and published instead. + /// UpdateIf the updating source currently owns the downstream value for this key, an Update is emitted. If a comparer is provided and the update causes a different source's value to become the best candidate, an Update is emitted with that other source's value. + /// RemoveIf the removed value was the one published downstream, the operator scans all remaining sources for the same key. If another source still holds that key, an Update is emitted with the replacement value (selected by comparer if provided, otherwise the next available). If no other source holds the key, a Remove is emitted. + /// RefreshIf the refreshed item matches the currently published value, the Refresh is forwarded. With a comparer, all sources are re-evaluated first; if a different value now wins, an Update is emitted instead of the Refresh. + /// OnErrorAn error from any source (outer or inner) terminates the entire merged output. + /// OnCompletedFor dynamic overloads, the output completes when the outer observable completes and all subscribed inner observables have also completed. For static overloads, completion depends on the completable parameter (default true). + /// + /// + /// Worth noting: When a source removes a key that was published downstream, the fallback to another + /// source's value is emitted as an Update (not an Add). This can be surprising if you expect + /// a Remove followed by an Add. Also, errors from any single inner source terminate the entire merged + /// stream, so consider error handling within individual sources if isolation is needed. + /// + /// + /// is null. + /// + /// public static IObservable> MergeChangeSets(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -2517,14 +2991,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using a comparer to resolve key conflicts. + /// When multiple sources provide the same key, the item ordering lowest according to + /// is published downstream. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// A unified changeset stream containing changes from all active source streams. + /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2536,14 +3012,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using an equality comparer to suppress + /// redundant updates. When an incoming value for a key is equal (per ) + /// to the currently published value, the update is suppressed. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// A unified changeset stream containing changes from all active source streams. + /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer) where TObject : notnull where TKey : notnull @@ -2555,15 +3033,16 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges dynamic cache changeset streams into a single output, using both a comparer for key conflict resolution + /// and an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// A unified changeset stream containing changes from all active source streams. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2576,16 +3055,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams into a single output. + /// Uses first-in-wins semantics for key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// The other of streams. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2597,17 +3077,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using a comparer for key conflict resolution. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// The other of streams. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Comparer to determine which value wins when both sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2620,17 +3100,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// The other of streams. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2643,18 +3123,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges both observable changesets into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Convenience overload that merges exactly two cache changeset streams, using both a comparer and an equality comparer. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// The other of streams. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The first changeset stream. + /// The second changeset stream to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Comparer to determine which value wins when both sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from both sources. + /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2668,16 +3148,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams into a single output. + /// Uses first-in-wins semantics for key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// An of of streams. Other Observable ChangeSets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2689,17 +3170,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using a comparer for key conflict resolution. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// An of of streams. Other Observable ChangeSets. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Comparer to determine which value wins when multiple sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2712,17 +3193,17 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// An of of streams. Other Observable ChangeSets. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2735,18 +3216,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. Merges the source changeset and the collection of other changesets together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges with additional changeset streams, using both a comparer and an equality comparer. /// - /// The type of the object. - /// The type of the key. - /// The source of . Observable ChangeSet. - /// An of of streams. Other Observable ChangeSets. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The primary changeset stream. + /// Additional changeset streams to merge with . + /// Equality comparer to detect duplicate values for the same key. + /// Comparer to determine which value wins when multiple sources provide the same key. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// A unified changeset stream containing changes from all sources. + /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2760,15 +3241,27 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single unified output. All source streams are + /// subscribed when the output observable is subscribed to. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// + /// + /// When multiple sources provide items with the same key, this overload uses first-in-wins semantics: + /// the first source to provide a key retains priority. Removing that source's item allows the next + /// available value for that key (if any) to surface. To control which value wins, use an overload + /// that accepts an . + /// + /// + /// An error from any source terminates the entire merged output. + /// + /// + /// is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2779,16 +3272,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using a comparer for key conflict + /// resolution. When multiple sources provide the same key, the item ordering lowest according to + /// is published downstream. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2800,16 +3295,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using an equality comparer to + /// suppress redundant updates. When an incoming value for a key is equal (per ) + /// to the currently published value, the update is suppressed. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2821,17 +3318,18 @@ public static IObservable> MergeChangeSets - /// Operator similar to Merge except it is ChangeSet aware. All of the observable changesets are merged together into a single stream of ChangeSet events that correctly handles multiple Keys. + /// Merges a fixed collection of cache changeset streams into a single output, using both a comparer for key + /// conflict resolution and an equality comparer to suppress redundant updates. /// - /// The type of the object. - /// The type of the key. - /// An of of streams. Source Observable ChangeSet. - /// instance to determine if two elements are the same. - /// instance to determine which element to emit if the same key is emitted from multiple changesets. - /// (Optional) instance to use when enumerating the collection. - /// Whether or not the result Observable should complete if all the changesets complete. - /// The result from merging the changesets together. - /// Parameter was null. + /// The type of items in the changesets. + /// The type of the key identifying items. + /// The collection of changeset streams to merge. + /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// Optional scheduler used when subscribing to the source streams. + /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// A unified changeset stream containing changes from all source streams. + /// , , or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) where TObject : notnull where TKey : notnull @@ -2844,17 +3342,19 @@ public static IObservable> MergeChangeSets - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. + /// The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2867,17 +3367,18 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. This overload requires a comparer for resolving destination key conflicts. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -2892,18 +3393,19 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child changes + /// into a single flattened output. The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A merged changeset stream containing items from all active child streams. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -2917,18 +3419,65 @@ public static IObservable> MergeManyCh } /// - /// Operator similar to MergeMany except it is ChangeSet aware. It uses to transform each item in the source into a child and merges the result children together into a single stream of ChangeSets that correctly handles multiple Keys and removal of the parent items. + /// For each item in the source cache, subscribes to a child changeset stream and merges all child + /// changes into a single flattened output stream. Child subscriptions track the parent item lifecycle: + /// created on Add, replaced on Update, disposed on Remove. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source (parent) cache. + /// The type of the key identifying parent items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream whose items each produce a child changeset stream. + /// Factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. + /// Optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. + /// Optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. + /// A merged changeset stream containing all child items from all active parent subscriptions. + /// + /// + /// This is the changeset-aware counterpart to . + /// Where MergeMany produces a flat IObservable<T>, MergeManyChangeSets produces an IObservable<IChangeSet> + /// that tracks the full lifecycle of child items, including key conflict resolution across parents. + /// + /// + /// Parent-side change handling (source changeset events): + /// + /// + /// EventBehavior + /// AddCalls with the new parent item to obtain a child changeset stream, then subscribes. As the child stream emits changesets, those child items are merged into the output. The downstream observer sees Add changes for each new child item. + /// UpdateDisposes the previous parent's child subscription (removing all of its contributed child items from the output as Remove changes), then creates a new child subscription for the updated parent. The new child's items appear as Add changes. + /// RemoveDisposes the parent's child subscription. All child items contributed by that parent are emitted as Remove changes in the output. If another parent also provides a child with the same destination key, that parent's value is promoted as an Update (not an Add). + /// RefreshNo effect on the child subscription. The parent's child stream continues unchanged. + /// + /// + /// Child-side change handling (changes arriving from child changeset streams): + /// + /// + /// EventBehavior + /// AddIf the destination key is new, an Add is emitted. If another parent already contributed a child with the same key, the conflict is resolved by (lowest wins) or first-in-wins if no comparer. The losing value is tracked internally but not emitted. + /// UpdateIf this parent currently owns the destination key downstream, an Update is emitted. With a comparer, all parents are re-evaluated for that key; a different parent's value may win, producing an Update to that value instead. + /// RemoveIf this parent's value was the one published downstream for that destination key, the operator scans other parents for the same key. If found, an Update is emitted with the replacement. If not, a Remove is emitted. + /// RefreshIf the child item is the one currently published downstream, the Refresh is forwarded. With a comparer, all parents are re-evaluated first; if a different value now wins, an Update is emitted instead. + /// + /// + /// Error and completion: + /// + /// + /// EventBehavior + /// OnErrorAn error from the source (parent) stream or from any child changeset stream terminates the entire output. Unlike , child errors are NOT swallowed. + /// OnCompletedThe output completes when the source (parent) stream completes and all active child changeset streams have also completed. + /// + /// + /// Worth noting: When multiple parents contribute children with the same destination key, only one value is published + /// downstream at a time. The controls which value wins; without it, the first parent to add the key + /// retains priority. Removing a parent that owned a contested key causes the next-best value (per comparer or next available) + /// to surface as an Update, not an Add. The independently controls whether a child + /// Update for an already-published key is suppressed when the new value equals the old. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TObject : notnull where TKey : notnull @@ -2942,19 +3491,21 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required . + /// Uses to resolve destination key conflicts by source priority. + /// The selector receives only the item, not its key. + /// Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -2968,19 +3519,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required . + /// Uses to resolve destination key conflicts by source priority. + /// Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -2988,20 +3540,20 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets with a required and + /// explicit control. The selector receives only the item. + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3015,20 +3567,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets with a required and + /// explicit control. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) where TObject : notnull where TKey : notnull @@ -3036,20 +3588,21 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, resortOnSourceRefresh, equalityComparer: null, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets. Uses to resolve + /// destination key conflicts. The selector receives only the item, not its key. + /// Source priorities are always re-evaluated on Refresh (default behavior). + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3063,20 +3616,20 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// Source-priority variant of MergeManyChangeSets. Uses to resolve + /// destination key conflicts. Source priorities are always re-evaluated on Refresh (default behavior). /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3084,21 +3637,21 @@ public static IObservable> MergeManyCh where TDestinationKey : notnull => source.MergeManyChangeSets(observableSelector, sourceComparer, DefaultResortOnSourceRefresh, equalityComparer, childComparer); /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// Source-priority variant of MergeManyChangeSets with full control over all conflict resolution parameters. + /// The selector receives only the item, not its key. + /// + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. + /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value. + /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A merged changeset stream with conflicts resolved by source priority. + /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3112,21 +3665,33 @@ public static IObservable> MergeManyCh } /// - /// Overload of that - /// will handle key collisions by using an instance that operates on the sources, so that the values from the preferred source take precedent over other values with the same. + /// For each item in the source cache, subscribes to a child cache changeset stream and merges all child + /// changes into a single flattened output. When multiple source items produce children with the same destination key, + /// determines which source has priority (the source ordering lower wins). + /// If sources compare equal, (if provided) breaks the tie. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The type of the destination key. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// instance to determine which source elements child to use when two sources provide a child element with the same key. - /// Optional boolean to indicate whether or not a refresh event in the parent stream should re-evaluate item priorities. - /// Optional instance to determine if two elements are the same. - /// Optional fallback instance to determine which child element to emit if the sources compare to be the same. - /// The result from merging the child changesets together. - /// Parameter was null. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child changeset streams. + /// The type of the key identifying child items. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child cache changeset stream. + /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// Optional fallback comparer to resolve destination key conflicts when source items compare equal. + /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. + /// + /// + /// The provides a layer of conflict resolution above the child values themselves. + /// This is useful when source items represent priority tiers (e.g., user settings overriding defaults). + /// + /// + /// Errors from child streams propagate to the output. An error from the source or any child terminates the merged output. + /// The output completes when the source completes and all active child streams have also completed. + /// + /// + /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) where TObject : notnull where TKey : notnull @@ -3141,15 +3706,17 @@ public static IObservable> MergeManyCh } /// - /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. + /// For each item in the source cache, subscribes to a child list changeset stream produced by + /// and merges all child changes into a single flattened list changeset output. + /// Child subscriptions follow the source item lifecycle: created on Add, replaced on Update, disposed on Remove. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// The result from merging the child changesets together. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child list changeset streams. + /// The source cache changeset stream. + /// Factory function that receives a source item and its key, and returns a child list changeset stream. + /// Optional equality comparer to detect duplicate items in the merged list output. + /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3162,15 +3729,16 @@ public static IObservable> MergeManyChangeSets - /// Merges the List ChangeSets derived from items in a Cache ChangeSet into a single observable list changeset. + /// For each item in the source cache, subscribes to a child list changeset stream and merges all child changes + /// into a single flattened list changeset output. The selector receives only the item, not its key. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . Observable ChangeSet. - /// A Factory Function used to create child changesets. - /// Optional instance to determine if two elements are the same. - /// The result from merging the child changesets together. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of items in the child list changeset streams. + /// The source cache changeset stream. + /// Factory function that receives a source item and returns a child list changeset stream. + /// Optional equality comparer to detect duplicate items in the merged list output. + /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -3181,18 +3749,17 @@ public static IObservable> MergeManyChangeSets - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. + /// Like , + /// but wraps each emitted value as an , pairing the source item + /// with the value it produced. This lets you identify which source item is responsible for each emission. /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . - /// A observable selector. - /// An observable which emits the item with the value. - /// source - /// or - /// observableSelector. + /// The type of items in the source cache. + /// The type of the key identifying source cache items. + /// The type of values emitted by child observables. + /// The source cache changeset stream. + /// Factory function that produces a child observable for each source item. + /// An observable of pairing each emission with its source item. + /// or is null. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3203,19 +3770,9 @@ public static IObservable> MergeManyItems(source, observableSelector).Run(); } - /// - /// Dynamically merges the observable which is selected from each item in the stream, and un-merges the item - /// when it is no longer part of the stream. - /// - /// The type of the object. - /// The type of the key. - /// The type of the destination. - /// The source of . - /// A observable selector. - /// An observable which emits the item with the value. - /// source - /// or - /// observableSelector. + /// + /// The source cache changeset stream. + /// Factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3227,22 +3784,26 @@ public static IObservable> MergeManyItems - /// Monitors the status of a stream. + /// Monitors the source observable and emits values: Pending initially, + /// Loaded when the first value arrives, Errored on error, and Completed on completion. + /// This is not a changeset operator. /// /// The type of the source observable. - /// An source. - /// An observable which monitors the status of the observable. - /// source. + /// The source observable to monitor. + /// An observable that emits values reflecting the source's lifecycle. + /// is null. + /// public static IObservable MonitorStatus(this IObservable source) => new StatusMonitor(source).Run(); /// - /// Suppresses updates which are empty. + /// Filters out empty changesets from the stream. A thin wrapper around Where(changes => changes.Count != 0). /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits change set values when not empty. - /// source. + /// The source changeset stream. + /// An observable that emits only non-empty changesets. + /// is null. + /// public static IObservable> NotEmpty(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3253,16 +3814,27 @@ public static IObservable> NotEmpty(thi } /// - /// Filters an observable changeset so that it only includes items that are of type . + /// Filters and casts items in the changeset to . Items that are not of type + /// are excluded. Combines filter and transform in one step without an intermediate cache. /// /// The type of the objects in the source changeset. /// The type of the key. - /// The type of the objects that are allowed to pass the filter. - /// The source of . Observable changeset of instances. - /// Indicates whether or not to suppress changesets that end up being empty after the conversion. - /// An observable changeset of where each item was either converted from or filtered out. - /// source. - /// Combines a filter and a transform into a single step that does not use an intermediate cache. + /// The destination type to filter and cast to. + /// The source observable changeset. + /// If true, changesets that become empty after filtering are suppressed. + /// An observable changeset of items. + /// + /// + /// EventBehavior + /// AddIf the item is , cast and emit as Add. Otherwise dropped. + /// UpdateRe-evaluated. If the new item is , emit accordingly. If the old item was downstream but the new one is not, emit Remove. + /// RemoveIf the item was downstream, emit Remove. + /// RefreshIf the item is downstream, forwarded as Refresh. + /// OnErrorForwarded to subscribers. + /// OnCompletedForwarded to subscribers. + /// + /// + /// is null. public static IObservable> OfType(this IObservable> source, bool suppressEmptyChangeSets = true) where TObject : notnull where TKey : notnull @@ -3278,9 +3850,28 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source of . - /// An add action that takes the new value and the associated key. - /// An observable which emits a change set with items being added. + /// The source changeset stream. + /// The callback invoked for each added item. Receives the new item and its key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddInvokes with the item and key. + /// UpdateIgnored. + /// RemoveIgnored. + /// RefreshIgnored. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3291,15 +3882,10 @@ public static IObservable> OnItemAdded( return source.OnChangeAction(ChangeReason.Add, addAction); } - /// - /// Callback for each item as and when it is being added to the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An add action that takes the new value. - /// An observable which emits a change set with items being added. - /// Overload for with a callback that doesn't use a key. + /// + /// The source changeset stream. + /// The callback invoked for each added item. Receives only the item (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3310,9 +3896,26 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source of . - /// An refresh action that takes the refreshed value and the key. - /// An observable which emits a change set with items being added. + /// The source changeset stream. + /// The callback invoked for each refreshed item. Receives the item and its key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored. + /// UpdateIgnored. + /// RemoveIgnored. + /// RefreshInvokes with the item and key. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull @@ -3323,34 +3926,54 @@ public static IObservable> OnItemRefreshed - /// Callback for each item as and when it is being refreshed in the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An refresh action that takes the refreshed value. - /// An observable which emits a change set with items being added. - /// Overload for with a callback that doesn't use a key. + /// + /// The source changeset stream. + /// The callback invoked for each refreshed item. Receives only the item (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull => source.OnItemRefreshed((obj, _) => refreshAction(obj)); /// - /// Callback for each item/key as and when it is being removed from the stream. + /// Invokes for each item with in the changeset stream. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An remove action that takes the removed value and the key. - /// Should the remove action be invoked when the subscription is disposed. - /// An observable which emits a change set with items being removed. - /// - /// source - /// or - /// removeAction. - /// + /// The source changeset stream. + /// The callback invoked for each removed item. Receives the removed item and its key. + /// + /// When true (the default), the callback is also invoked for every item still in the cache + /// when the subscription is disposed. When false, only inline Remove changes trigger the callback. + /// + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored (but tracked internally when is true). + /// UpdateIgnored (cache updated internally when is true). + /// RemoveInvokes with the item and key. + /// RefreshIgnored. + /// + /// + /// + /// Unsubscribe behavior: when is true, the operator + /// maintains an internal cache mirroring the stream. On disposal, it iterates all remaining items and + /// invokes for each. This is useful for cleanup logic (e.g. event unsubscription) + /// that must run for items that were never explicitly removed. + /// + /// + /// Exceptions thrown in propagate as OnError during inline removes. + /// During unsubscribe disposal, exceptions are not caught. + /// + /// Worth noting: The action also fires for ALL remaining items when the subscription is disposed (unless invokeOnUnsubscribe is false). The action runs under a lock; avoid calling into other caches from within it. + /// + /// or is null. + /// + /// public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull @@ -3366,34 +3989,43 @@ public static IObservable> OnItemRemoved - /// Callback for each item as and when it is being removed from the stream. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An remove action that takes the removed value. - /// Should the remove action be invoked when the subscription is disposed. - /// An observable which emits a change set with items being removed. - /// - /// source - /// or - /// removeAction. - /// - /// Overload for with a callback that doesn't use the key. + /// + /// The source changeset stream. + /// The callback invoked for each removed item. Receives only the item (no key). + /// When true (the default), also invoked for all remaining items on disposal. + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull => source.OnItemRemoved((obj, _) => removeAction(obj), invokeOnUnsubscribe); /// - /// Callback when an item has been updated eg. (current, previous)=>{}. + /// Invokes for each item with in the changeset stream. + /// The changeset is forwarded downstream unchanged. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An update action that takes current value, previous value, and the key. - /// An observable which emits a change set with items being updated. + /// The source changeset stream. + /// The callback invoked for each updated item. Receives the current value, previous value, and key. + /// A stream that forwards all changesets from unchanged. + /// + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddIgnored. + /// UpdateInvokes with (current, previous, key). The previous value is always available for Update changes. + /// RemoveIgnored. + /// RefreshIgnored. + /// + /// + /// + /// Exceptions thrown in propagate as OnError. No try-catch is applied. + /// + /// + /// or is null. + /// + /// public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull @@ -3404,33 +4036,43 @@ public static IObservable> OnItemUpdated change.Reason == ChangeReason.Update, change => updateAction(change.Current, change.Previous.Value, change.Key)); } - /// - /// Callback when an item has been updated eg. (current, previous)=>{}. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// An update action that takes the current value and previous value. - /// An observable which emits a change set with items being updated. - /// Overload for with a callback that doesn't use the key. + /// + /// The source changeset stream. + /// The callback invoked for each updated item. Receives only the current and previous values (no key). + /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull where TKey : notnull => source.OnItemUpdated((cur, prev, _) => updateAction(cur, prev)); /// - /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. + /// Combines multiple changeset streams using logical OR (union). An item appears downstream if it exists in any source. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The other of streams. - /// An observable which emits change sets. - /// - /// source - /// or - /// others. - /// + /// The first source changeset stream. + /// Additional changeset streams to combine with. + /// A changeset stream containing items present in any of the sources. + /// + /// + /// Items are tracked via reference counting across all sources. An item appears downstream as long as + /// at least one source contains it. When the last source holding a key removes it, the item is removed downstream. + /// + /// + /// EventBehavior + /// AddIf this is the first source to provide the key, an Add is emitted. If other sources already have the key, the reference count is incremented but no emission occurs. + /// UpdateIf the item is currently downstream, an Update is emitted. + /// RemoveReference count decremented. If the count reaches zero (no source holds the key), a Remove is emitted. Otherwise no emission. + /// RefreshIf the item is downstream, a Refresh is forwarded. + /// OnErrorAn error from any source terminates the combined output. + /// OnCompletedThe output completes when all sources have completed. + /// + /// + /// or is null. + /// + /// + /// + /// public static IObservable> Or(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -3445,18 +4087,9 @@ public static IObservable> Or(this IObs return source.Combine(CombineOperator.Or, others); } - /// - /// Apply a logical Or operator between the collections i.e items which are in any of the sources are included. - /// - /// The type of the object. - /// The type of the key. - /// An of of streams. source. - /// An observable which emits change sets. - /// - /// source - /// or - /// others. - /// + /// + /// A fixed collection of changeset streams to combine. + /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Or(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -3472,7 +4105,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// An of of streams. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -3489,7 +4122,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -3506,7 +4139,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -3518,18 +4151,19 @@ public static IObservable> Or(this IObs } /// - /// Populate a cache from an observable stream. + /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted batch of items. /// /// The type of the object. /// The type of the key. - /// The source. - /// An of observable. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// keySelector. - /// + /// The source cache to populate. + /// The observable that emits batches of items. + /// An that, when disposed, unsubscribes from . + /// + /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. + /// + /// or is null. + /// + /// public static IDisposable PopulateFrom(this ISourceCache source, IObservable> observable) where TObject : notnull where TKey : notnull @@ -3540,18 +4174,14 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Populate a cache from an observable stream. + /// Subscribes to the observable and calls AddOrUpdate on the source cache for each emitted item. /// /// The type of the object. /// The type of the key. - /// The source. - /// An observable. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// keySelector. - /// + /// The source cache to populate. + /// The observable that emits individual items. + /// An that, when disposed, unsubscribes from . + /// or is null. public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) where TObject : notnull where TKey : notnull @@ -3562,18 +4192,30 @@ public static IDisposable PopulateFrom(this ISourceCache - /// Populates a source into the specified cache. + /// Subscribes to the changeset stream and clones each changeset into the destination cache. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The destination. - /// A disposable which will unsubscribe from the source. - /// - /// source - /// or - /// destination. - /// + /// The source changeset stream. + /// The destination cache to populate. + /// An that, when disposed, unsubscribes from the source. + /// + /// + /// Each changeset from the source is applied to the destination cache inside an Edit call. + /// + /// + /// EventBehavior + /// AddThe item is added to the destination cache via AddOrUpdate. + /// UpdateThe item is updated in the destination cache via AddOrUpdate. + /// RemoveThe item is removed from the destination cache. + /// RefreshA Refresh is issued on the destination cache for the item. + /// OnErrorThe subscription is terminated. The destination cache is not rolled back. + /// OnCompletedThe subscription ends. The destination cache retains all items. + /// + /// + /// or is null. + /// + /// public static IDisposable PopulateInto(this IObservable> source, ISourceCache destination) where TObject : notnull where TKey : notnull @@ -3584,17 +4226,10 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// Populates a source into the specified cache. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The destination. - /// A disposable which will unsubscribe from the source. - /// source - /// or - /// destination. + /// + /// The source changeset stream. + /// The destination intermediate cache to populate. + /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) where TObject : notnull where TKey : notnull @@ -3605,14 +4240,10 @@ public static IDisposable PopulateInto(this IObservable destination.Edit(updater => updater.Clone(changes))); } - /// - /// Populates a source into the specified cache. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The destination. - /// A disposable which will unsubscribe from the source. + /// + /// The source changeset stream. + /// The destination lock-free cache to populate. + /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) where TObject : notnull where TKey : notnull @@ -3624,19 +4255,30 @@ public static IDisposable PopulateInto(this IObservable - /// The latest copy of the cache is exposed for querying after each modification to the underlying data. + /// Projects the current cache state through after each modification. + /// Emits a new value of on every changeset. /// /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source of . - /// A result selector. - /// An observable which emits the destination values. - /// - /// source - /// or - /// resultSelector. - /// + /// The source changeset stream. + /// Projects the current snapshot to a result value. + /// An observable that emits a projected value after each changeset. + /// + /// + /// EventBehavior + /// AddCache updated, then invoked and result emitted. + /// UpdateCache updated, then invoked and result emitted. + /// RemoveCache updated, then invoked and result emitted. + /// RefreshCache updated, then invoked and result emitted. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: The selector is called on every changeset, which can be chatty. The exposes the full cache state for LINQ-style queries. + /// + /// or is null. + /// + /// public static IObservable QueryWhenChanged(this IObservable> source, Func, TDestination> resultSelector) where TObject : notnull where TKey : notnull @@ -3652,7 +4294,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source of . + /// The source changeset stream. /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -3670,8 +4312,8 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// The source of . - /// A Should the query be triggered for observables on individual items. + /// The source changeset stream. + /// Should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source, Func> itemChangedTrigger) @@ -3685,12 +4327,14 @@ public static IObservable> QueryWhenChanged - /// Cache equivalent to Publish().RefCount(). The source is cached so long as there is at least 1 subscriber. + /// Cache-aware equivalent of Publish().RefCount(). An internal cache is created on the first subscriber + /// and disposed when the last subscriber unsubscribes. All subscribers share the same upstream subscription. /// /// The type of the object. - /// The type of the destination key. - /// The source of . - /// An observable which emits change sets that are ref counted. + /// The type of the key. + /// The source changeset stream. + /// A ref-counted observable changeset stream. + /// public static IObservable> RefCount(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3701,13 +4345,23 @@ public static IObservable> RefCount(thi } /// - /// Signal observers to re-evaluate the specified item. + /// Signals downstream operators to re-evaluate the specified item. Produces a changeset with a single Refresh change. /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to refresh. + /// + /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. + /// + /// EventBehavior + /// RefreshProduced for the specified item. Downstream operators re-evaluate this item against their current logic (filter predicate, sort comparer, group key selector, etc.). + /// OtherNo Add, Update, or Remove events are produced by this method. + /// + /// + /// is null. + /// + /// public static void Refresh(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -3718,13 +4372,13 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signal observers to re-evaluate the specified items. + /// Signals downstream operators to re-evaluate the specified items. Produces one changeset with a Refresh for each item. /// /// The type of the object. /// The type of the key. - /// The source. - /// An items. - /// source. + /// The source cache. + /// The items to refresh. + /// is null. public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -3735,12 +4389,12 @@ public static void Refresh(this ISourceCache sourc } /// - /// Signal observers to re-evaluate the all items. + /// Signals downstream operators to re-evaluate all items in the cache. Produces one changeset with a Refresh for every item. /// /// The type of the object. /// The type of the key. - /// The source. - /// source. + /// The source cache. + /// is null. public static void Refresh(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -3751,14 +4405,24 @@ public static void Refresh(this ISourceCache sourc } /// - /// Removes the specified item from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes the specified item from the cache. Produces a Remove changeset if the item exists, nothing otherwise. /// /// The type of the object. /// The type of the key. - /// The source. - /// The item. - /// source. + /// The source cache. + /// The item to remove. + /// + /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. + /// + /// EventBehavior + /// RemoveProduced if the key exists in the cache. The removed value is included in the changeset. + /// OtherNo Add, Update, or Refresh events are produced by this method. + /// + /// + /// is null. + /// + /// + /// public static void Remove(this ISourceCache source, TObject item) where TObject : notnull where TKey : notnull @@ -3769,14 +4433,13 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes the item with the specified key from the cache. Produces a Remove changeset if the key exists, nothing otherwise. /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// source. + /// The source cache. + /// The key of the item to remove. + /// is null. public static void Remove(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3787,14 +4450,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified items from the cache. - /// Any items not contained in the cache are ignored. + /// Removes the specified items from the cache. Any items not present in the cache are ignored. + /// Produces a Remove changeset for each item that existed. /// /// The type of the object. /// The type of the key. - /// The source. - /// An items. - /// source. + /// The source cache. + /// The items to remove. + /// is null. public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -3805,14 +4468,14 @@ public static void Remove(this ISourceCache source } /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. + /// Removes the items with the specified keys from the cache. Any keys not present are ignored. + /// Produces a Remove changeset for each key that existed. /// /// The type of the object. /// The type of the key. - /// The source. - /// An keys. - /// source. + /// The source cache. + /// The keys to remove. + /// is null. public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3822,15 +4485,10 @@ public static void Remove(this ISourceCache source source.Edit(updater => updater.Remove(keys)); } - /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// The key. - /// source. + /// + /// The intermediate cache. + /// The key of the item to remove. + /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3840,15 +4498,10 @@ public static void Remove(this IIntermediateCache source.Edit(updater => updater.Remove(key)); } - /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. - /// - /// The type of the object. - /// The type of the key. - /// The source. - /// An keys. - /// source. + /// + /// The intermediate cache. + /// The keys to remove. + /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3859,15 +4512,14 @@ public static void Remove(this IIntermediateCache } /// - /// Removes the key which enables all observable list features of dynamic data. + /// Strips the key from a cache changeset, converting to + /// (list changeset). All indexed changes are dropped (sorting is not supported). /// - /// - /// All indexed changes are dropped i.e. sorting is not supported by this function. - /// - /// The type of object. - /// The type of key. - /// The source of . - /// An observable which emits change sets. + /// The type of the object. + /// The type of the key. + /// The source changeset stream. + /// A list changeset stream without key information. + /// public static IObservable> RemoveKey(this IObservable> source) where TObject : notnull where TKey : notnull @@ -3883,14 +4535,13 @@ public static IObservable> RemoveKey(this IOb } /// - /// Removes the specified key from the cache. - /// If the item is not contained in the cache then the operation does nothing. + /// Removes a specific key from the cache. Equivalent to source.Edit(u => u.RemoveKey(key)). /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// source. + /// The source cache. + /// The key to remove. + /// is null. public static void RemoveKey(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -3901,14 +4552,13 @@ public static void RemoveKey(this ISourceCache sou } /// - /// Removes the specified keys from the cache. - /// Any keys not contained in the cache are ignored. + /// Removes multiple keys from the cache in a single Edit call. Keys not present in the cache are ignored. /// /// The type of the object. /// The type of the key. - /// The source. - /// An keys. - /// source. + /// The source cache. + /// The keys to remove. + /// is null. public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -3918,19 +4568,12 @@ public static void RemoveKeys(this ISourceCache so source.Edit(updater => updater.RemoveKeys(keys)); } - /// - /// Joins the left and right observable data sources, taking all right values and combining any matching left values. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -3947,18 +4590,48 @@ public static IObservable> RightJoin - /// Joins the left and right observable data sources, taking all right values and combining any matching left values. + /// Joins two changeset streams, producing a result for every right-side key. The left side is + /// because a matching left item may or may not exist. All right items + /// appear in the output regardless. Equivalent to SQL RIGHT OUTER JOIN. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). + /// An observable changeset keyed by . + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddAlways emits. Invokes with the matching left (or Optional.None) and the right value. + /// UpdateRe-invokes the selector with current left (if any) and the new right value. + /// RemoveRemoves the joined result. + /// RefreshForwarded as Refresh on the joined result. + /// + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf matching right items exist, re-invokes the selector (left transitions from None to Some) and emits Updates. + /// UpdateIf matching right items exist, re-invokes the selector with the new left value. + /// RemoveIf matching right items exist, re-invokes the selector (left transitions from Some to None) and emits Updates. + /// RefreshIf joined results exist, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -3974,20 +4647,12 @@ public static IObservable> RightJoin(left, right, rightKeySelector, resultSelector).Run(); } - /// - /// Groups the right data source and joins the two sources matching them using the specified key selector, , taking all right values and combining any matching left values. - /// This is the equivalent of SQL left join. - /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4004,19 +4669,49 @@ public static IObservable> RightJoinMany - /// Groups the right data source and joins the two sources matching them using the specified key selector,, taking all right values and combining any matching left values. - /// This is the equivalent of SQL left join. + /// Groups right-side items by their mapped key, then right-joins each group to the left source. + /// A result is produced for every key that has at least one right item. The left value is + /// because a matching left item may or may not exist. + /// Equivalent to SQL RIGHT OUTER JOIN with the right side grouped. /// - /// The object type of the left data source. - /// The key type of the left data source. - /// The object type of the right data source. - /// The key type of the right data source. - /// The resulting object which. - /// The left of data source. - /// The right of data source. - /// A Specify the foreign key on the right data source. - /// A result selector.used to transform the combined data into. Example (key, left, right) => new CustomObject(key, left, right). - /// An observable which will emit change sets. + /// The item type of the left source. + /// The key type of the left source. + /// The item type of the right source. + /// The key type of the right source. + /// The type produced by . + /// The left changeset stream. + /// The right changeset stream. + /// Maps each right item to the left key it should join on. + /// Combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// An observable changeset keyed by . + /// + /// + /// Right-side change handling: + /// + /// EventBehavior + /// AddUpdates the right group. If the group was previously empty, emits an Add with the current left (if any). Otherwise emits an Update. + /// UpdateUpdates the right group and re-invokes . + /// RemoveUpdates the right group. If the group becomes empty, removes the joined result. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// + /// Left-side change handling: + /// + /// EventBehavior + /// AddIf a non-empty right group exists, re-invokes the selector (left transitions from None to Some) and emits an Update. + /// UpdateIf a non-empty right group exists, re-invokes the selector with the new left value. + /// RemoveIf a non-empty right group exists, re-invokes the selector (left transitions from Some to None) and emits an Update. + /// RefreshIf a joined result exists, forwarded as Refresh. + /// + /// + /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. + /// + /// Any argument is null. + /// + /// + /// + /// public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull where TLeftKey : notnull @@ -4033,13 +4728,16 @@ public static IObservable> RightJoinMany - /// Defer the subscription until loaded and skip initial change set. + /// Skips the initial snapshot changeset that Connect() typically emits, then forwards all subsequent changesets. + /// Internally uses DeferUntilLoaded().Skip(1). /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits change sets. - /// source. + /// The source changeset stream. + /// An observable that skips the first changeset and forwards all others. + /// is null. + /// + /// public static IObservable> SkipInitial(this IObservable> source) where TObject : notnull where TKey : notnull @@ -4050,15 +4748,13 @@ public static IObservable> SkipInitial( } /// - /// Sorts using the specified comparer. - /// Returns the underlying ChangeSet as per the system conventions. - /// The resulting change set also exposes a sorted key value collection of the underlying cached data. + /// Obsolete: use SortAndBind instead. Sorts using the specified comparer. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An comparer. - /// The Sort optimisation flags. Specify one or more sort optimisations. + /// The source changeset stream. + /// The comparer. + /// Sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). /// An observable which emits change sets. /// @@ -4078,13 +4774,13 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed. - /// The sort optimisations. + /// The source changeset stream. + /// The comparer observable. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4099,14 +4795,14 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a dynamic comparer observable with a manual re-sort signal. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An of which enables the sort order to be changed. - /// An of Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// The source changeset stream. + /// The comparer observable. + /// Signal to instruct the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4121,14 +4817,14 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence as, using the comparer observable to determine order. + /// Obsolete: use SortAndBind instead. Sorts using a static comparer with a manual re-sort signal. /// /// The type of the object. /// The type of the key. - /// The source of . - /// An comparer to sort on. - /// An of Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// The source changeset stream. + /// The comparer to sort on. + /// Signal to instruct the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4143,16 +4839,18 @@ public static IObservable> Sort(t } /// - /// Sorts a sequence by selected property. + /// Sorts the changeset stream by the value returned from . Creates a comparer internally + /// and delegates to . + /// Since Sort is obsolete, prefer SortAndBind for new code. /// /// The type of the object. /// The type of the key. - /// The source of . - /// A expression. - /// The sort order. Defaults to ascending. - /// The sort optimisations. - /// The reset threshold. - /// An observable which emits change sets. + /// The source changeset stream. + /// Expression that selects a comparable value from each item. + /// The sort direction. Defaults to ascending. + /// Sort optimization flags. + /// The number of updates before the entire list is re-sorted (rather than inline sort). + /// An observable that emits sorted changesets. public static IObservable> SortBy( this IObservable> source, Func expression, @@ -4176,91 +4874,76 @@ public static IObservable> SortBy } /// - /// Prepends an empty change set to the source. + /// Prepends an empty changeset to the source stream, ensuring subscribers always receive an immediate + /// (empty) notification on subscription. Uses Rx's StartWith. /// - /// The object of the change set. - /// The key of the change set. - /// The source of . Observable change set. - /// An observable which emits change sets. + /// The type of the object. + /// The type of the key. + /// The source observable change set. + /// An observable that emits an empty changeset first, then all source changesets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source of . Observable change set. - /// An observable which emits sorted change sets. + /// + /// The source observable sorted change set. + /// An observable that emits an empty sorted changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(SortedChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source of . Observable change set. - /// An observable which emits virtual change sets. + /// + /// The source observable virtual change set. + /// An observable that emits an empty virtual changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(VirtualChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. - /// The source of . Observable change set. - /// An observable which emits paged change sets. + /// + /// The source observable paged change set. + /// An observable that emits an empty paged changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(PagedChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. + /// + /// The type of the object. + /// The type of the key. /// The grouping key type. - /// An source observable change set. - /// An observable which emits group change sets. + /// The source observable group change set. + /// An observable that emits an empty group changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(GroupChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// - /// The object of the change set. - /// The key of the change set. + /// + /// The type of the object. + /// The type of the key. /// The grouping key type. - /// An source observable change set. - /// An observable which emits immutable group change sets. + /// The source observable immutable group change set. + /// An observable that emits an empty immutable group changeset first, then all source changesets. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull where TGroupKey : notnull => source.StartWith(ImmutableGroupChangeSet.Empty); - /// - /// Prepends an empty change set to the source. - /// + /// /// The type of the item. - /// An source read only collection. - /// A read only collection. + /// The source read only collection observable. + /// An observable that emits an empty collection first, then all source collections. + /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); - /// - /// The equivalent of rx StartsWith operator, but wraps the item in a change where reason is ChangeReason.Add. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The item. - /// An observable which emits change sets. + /// + /// The source changeset stream. + /// The item to prepend. The key is extracted from . + /// Overload for items that implement . Delegates to the explicit key overload. public static IObservable> StartWithItem(this IObservable> source, TObject item) where TObject : IKey where TKey : notnull @@ -4271,14 +4954,15 @@ public static IObservable> StartWithItem - /// The equivalent of rx StartWith operator, but wraps the item in a change where reason is ChangeReason.Add. + /// Prepends a changeset containing a single Add for the given item and key to the source stream. + /// The Rx equivalent of StartWith, but wrapped as a DynamicData changeset. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The item. - /// The key. - /// An observable which emits change sets. + /// The source changeset stream. + /// The item to prepend. + /// The key for the item. + /// An observable that emits a single-item Add changeset first, then all source changesets. public static IObservable> StartWithItem(this IObservable> source, TObject item, TKey key) where TObject : notnull where TKey : notnull @@ -4290,19 +4974,38 @@ public static IObservable> StartWithItem - /// Subscribes to each item when it is added to the stream and un-subscribes when it is removed. All items will be unsubscribed when the stream is disposed. + /// Creates an subscription per item via . + /// Subscriptions are created on Add/Update and disposed on Update/Remove. All active subscriptions + /// are disposed when the stream completes, errors, or the subscription is disposed. /// /// The type of the object. /// The type of the key. - /// The source of . - /// A subscription function. - /// An observable which emits a change set. - /// source - /// or - /// subscriptionFactory. + /// The source changeset stream. + /// Factory that creates an for each item. Called on Add and Update (for the new value). + /// A stream that forwards all changesets from unchanged. /// - /// Subscribes to each item when it is added or updates and un-subscribes when it is removed. + /// + /// Change reason handling: + /// + /// EventBehavior + /// AddCalls , stores the returned . + /// UpdateDisposes the previous subscription, then calls for the new value. + /// RemoveDisposes the subscription for the removed item. + /// RefreshPassed through. No subscription change. + /// + /// + /// + /// Internally implemented using + /// and , so disposal semantics match . + /// + /// + /// Use this to tie per-item side effects (event subscriptions, polling timers, child observable subscriptions) + /// to the lifecycle of items in the cache. + /// /// + /// or is null. + /// + /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -4313,20 +5016,10 @@ public static IObservable> SubscribeMany(source, subscriptionFactory).Run(); } - /// - /// Subscribes to each item when it is added to the stream and unsubscribes when it is removed. All items will be unsubscribed when the stream is disposed. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// A subscription function. - /// An observable which emits a change set. - /// source - /// or - /// subscriptionFactory. - /// - /// Subscribes to each item when it is added or updates and unsubscribes when it is removed. - /// + /// + /// The source changeset stream. + /// Factory that creates an for each item. Receives the item and its key. + /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -4342,24 +5035,15 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// The source of . Observable change set. + /// The source observable change set. /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull where TKey : notnull => source.WhereReasonsAreNot(ChangeReason.Refresh); - /// - /// Transforms an observable sequence of observable caches into a single sequence - /// producing values only from the most recent observable sequence. - /// Each time a new inner observable sequence is received, unsubscribe from the - /// previous inner observable sequence and clear the existing result set. - /// - /// The type of the object. - /// The type of the key. - /// An source. - /// - /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. - /// + /// + /// An observable that emits instances. + /// Overload that accepts observable caches. Internally calls Connect() on each cache and delegates to the changeset overload. public static IObservable> Switch(this IObservable> sources) where TObject : notnull where TKey : notnull @@ -4370,17 +5054,26 @@ public static IObservable> Switch(this } /// - /// Transforms an observable sequence of observable changes sets into an observable sequence - /// producing values only from the most recent observable sequence. - /// Each time a new inner observable sequence is received, unsubscribe from the - /// previous inner observable sequence and clear the existing result set. + /// Subscribes to the latest inner changeset stream, unsubscribing from the previous one on each switch. + /// When switching, the old source's items are removed and the new source's items are added. /// /// The type of the object. /// The type of the key. - /// An of of streams. source. - /// - /// The observable sequence that at any point in time produces the elements of the most recent inner observable sequence that has been received. - /// + /// An observable that emits inner changeset streams. + /// A changeset stream reflecting the items from the most recently emitted inner source. + /// + /// + /// EventBehavior + /// AddForwarded from the active inner source. + /// UpdateForwarded from the active inner source. + /// RemoveForwarded from the active inner source. + /// RefreshForwarded from the active inner source. + /// OnErrorAn error from any inner source or the outer source terminates the stream. + /// OnCompletedCompletes when the outer source and the current inner source have both completed. + /// + /// On switch: Remove is emitted for all items from the previous source, then Add for all items from the new source. + /// Worth noting: Each switch clears the entire downstream cache before populating from the new source. Subscribers see a full remove-then-add reset on every switch. + /// public static IObservable> Switch(this IObservable>> sources) where TObject : notnull where TKey : notnull @@ -4395,27 +5088,26 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source changeset stream. /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull where TKey : notnull => source.QueryWhenChanged(query => new ReadOnlyCollectionLight(query.Items)); /// - /// Converts the observable to an observable change set. - /// Change set observes observable change events. + /// Bridges a standard Rx observable of individual items into a DynamicData changeset stream. + /// Each emission becomes an Add (or Update if the key already exists). + /// Supports optional per-item expiration and size limiting. /// /// The type of the object. /// The type of the key. - /// An source. - /// A key selector. - /// A Specify on a per object level the maximum time before an object expires from a cache. - /// Remove the oldest items when the size has reached this limit. - /// The scheduler (only used for time expiry). - /// An observable which will emit changes. - /// source - /// or - /// keySelector. + /// The source observable of individual items. + /// Selects the unique key for each item. + /// Optional: per-item expiration time. Return null for no expiration. + /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// Optional scheduler for expiration timing. + /// An observable changeset stream. + /// or is null. public static IObservable> ToObservableChangeSet( this IObservable source, Func keySelector, @@ -4437,20 +5129,19 @@ public static IObservable> ToObservableChangeSet - /// Converts the observable to an observable change set. - /// Change set observes observable change events. + /// Bridges a standard Rx observable of item batches into a DynamicData changeset stream. + /// Each batch is processed with AddOrUpdate, producing Add or Update changes per item. + /// Supports optional per-item expiration and size limiting. /// /// The type of the object. /// The type of the key. - /// An of source. - /// A key selector. - /// A Specify on a per object level the maximum time before an object expires from a cache. - /// Remove the oldest items when the size has reached this limit. - /// The scheduler (only used for time expiry). - /// An observable change set. - /// source - /// or - /// keySelector. + /// The source observable of item batches. + /// Selects the unique key for each item. + /// Optional: per-item expiration time. Return null for no expiration. + /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// Optional scheduler for expiration timing. + /// An observable changeset stream. + /// or is null. public static IObservable> ToObservableChangeSet( this IObservable> source, Func keySelector, @@ -4472,15 +5163,34 @@ public static IObservable> ToObservableChangeSet - /// Converts an observable change set into an observable optional that emits the value for the given key. + /// Watches a single key in the source changeset stream, emitting Optional.Some(value) when the key + /// is present and Optional.None when it is removed. Duplicate values are suppressed via . /// /// The type of the object. /// The type of the key. - /// The source of . - /// The key value. - /// Optional instance used to determine if an object value has changed. - /// An observable optional. - /// source is null. + /// The source changeset stream. + /// The key to watch. + /// Optional comparer to suppress duplicate emissions. Uses default equality if null. + /// An observable of that reflects the presence or absence of the specified key. + /// + /// + /// Unlike , this emits None on removal + /// (rather than the removed value), making it possible to distinguish "key is absent" from "key has a value". + /// + /// + /// EventBehavior + /// AddEmits Optional.Some(value) if the key was not previously tracked. + /// UpdateEmits Optional.Some(newValue) if the new value differs from the previous per . Otherwise suppressed. + /// RemoveEmits Optional.None. + /// RefreshEmits Optional.Some(value) if the value differs from the last emission per . Otherwise suppressed. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No emission occurs if the key is not present at subscription time. To get an initial None when the key is absent, use the overload with initialOptionalWhenMissing: true. + /// + /// is null. + /// + /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -4495,12 +5205,15 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source changeset stream. /// The key value. /// Indicates if an initial Optional None should be emitted if the value doesn't exist. /// Optional instance used to determine if an object value has changed. /// An observable optional. /// source is null. + /// + /// Worth noting: Uses lock-based coordination. If the key exists synchronously on Connect(), the initial None may or may not be emitted depending on timing. + /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, bool initialOptionalWhenMissing, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -4525,9 +5238,9 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// The source of . - /// A sort function. - /// The sort order. Defaults to ascending. + /// The source changeset stream. + /// The sort function. + /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, Func sort, SortDirection sortOrder = SortDirection.Ascending) where TObject : notnull @@ -4539,8 +5252,8 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// The source of . - /// An sort comparer. + /// The source changeset stream. + /// The sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) where TObject : notnull @@ -4552,21 +5265,8 @@ public static IObservable> ToSortedCollection(items); }); - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4578,21 +5278,8 @@ public static IObservable> Transform transformFactory(current), transformOnRefresh); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4604,21 +5291,8 @@ public static IObservable> Transform transformFactory(current, key), transformOnRefresh); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -4630,21 +5304,8 @@ public static IObservable> Transform(source, transformFactory, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts an optional forceTransform predicate filtering by source item only (without the key). The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4656,21 +5317,8 @@ public static IObservable> Transform transformFactory(current), forceTransform?.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts an optional forceTransform predicate filtering by source item and key. The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4683,20 +5331,43 @@ public static IObservable> Transform - /// Projects each update item to a new form using the specified transform function. + /// Projects each item in the changeset to a new form using a synchronous transform factory. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Transform maintains a 1:1 mapping between source and destination items, keyed identically. The factory + /// is called once per Add and once per Update. Removes are forwarded without calling the factory. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls factory, emits Add. + /// UpdateCalls factory (receives current item, previous item, key), emits Update with Previous preserved. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshForwarded as Refresh without re-transforming. To re-transform on Refresh, use the parameter or the transformOnRefresh overloads. + /// + /// Worth noting: By default, Refresh does NOT re-invoke the transform factory (it is just forwarded). Set transformOnRefresh: true to re-transform on Refresh. + /// + /// When emits a predicate, every cached item is tested against it. + /// Matching items are re-transformed and emitted as Updates. + /// + /// + /// Factory exceptions propagate as , terminating the stream. + /// Use + /// to catch factory errors without killing the stream. + /// + /// + /// + /// + /// + /// or is null. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -4712,41 +5383,15 @@ public static IObservable> Transform(source, transformFactory).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of Invoke to force a new transform for all items. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.Transform((cur, _, _) => transformFactory(cur), forceTransform.ForForced()); - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -4759,21 +5404,8 @@ public static IObservable> Transform transformFactory(cur, key), forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items when the observable emits. public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -4786,21 +5418,8 @@ public static IObservable> Transform()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a simpler factory that receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4813,21 +5432,8 @@ public static IObservable> TransformAsync transformFactory(current), forceTransform); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4841,20 +5447,38 @@ public static IObservable> TransformAsync - /// Projects each update item to a new form using the specified transform function. + /// Async version of . + /// Projects each item using an async factory that returns . /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// An async function that produces a from the current source item, the previous source item (if any), and the key. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Transforms within a single changeset batch execute concurrently. The entire batch must complete + /// before the resulting changeset is emitted. Use the overloads + /// to control maximum concurrency and Refresh handling. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddAwaits factory, emits Add. + /// UpdateAwaits factory (receives current, previous, key), emits Update. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshForwarded as Refresh by default. Use to re-transform. + /// + /// Worth noting: Transforms are batched per changeset (all tasks must complete before the next changeset is processed). Completion waits for in-flight transforms. Remove does NOT cancel in-flight transforms for the removed key. + /// + /// Factory exceptions propagate as . Use + /// + /// to catch factory errors without terminating the stream. + /// + /// + /// or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -4867,21 +5491,8 @@ public static IObservable> TransformAsync(source, transformFactory, null, forceTransform).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4894,21 +5505,8 @@ public static IObservable> TransformAsync transformFactory(current), options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4921,21 +5519,8 @@ public static IObservable> TransformAsync transformFactory(current, key), options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// The transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, TransformAsyncOptions options) where TDestination : notnull @@ -4949,26 +5534,31 @@ public static IObservable> TransformAsync - /// Projects each update item to a new form using the specified transform function, with optimizations for stateless/deterministic transformation of immutable items. + /// Optimized transform for immutable items with deterministic (pure) transform functions. + /// Refresh changes are dropped entirely since immutable items cannot change in place. /// - /// The type of collection items produced by the transformation. - /// The type of collection items to be transformed. - /// The type of the key values of each collection item. - /// The source of . Stream of collection items to be transformed. - /// A transformation to be applied to each item. - /// A stream of collection changesets where upstream collection items are transformed by the given factory function. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. + /// An observable changeset of transformed items. /// - /// The goal of this operator is to optimize a common use-case of reactive programming, where data values flowing through a stream are immutable, and state changes are distributed by publishing new immutable items as replacements, instead of mutating the items directly. - /// In addition to assuming that all collection items are immutable, this operator also assumes that the given transformation function is deterministic, such that the result it returns will always be equivalent each time a specific input is passed to it. In other words, the transformation itself also contains no mutable state. - /// Under these assumptions, this operator can bypass the need to keep track of every collection item that passes through it, which the normal operator must do, in order to re-evaluate transformations during a refresh operation. - /// Consider using this operator when the following are true: - /// - /// Your collection items are immutable, and changes are published by replacing entire items - /// Your transformation logic does not change over the lifetime of the stream, only the items do - /// Your transformation function runs quickly, and does not heavily allocate memory + /// + /// Because the transform is assumed to be stateless and deterministic, this operator does not track + /// previously transformed items. This reduces memory overhead compared to . + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls factory, emits Add. + /// UpdateCalls factory, emits Update. + /// RemoveEmits Remove. Factory is NOT called. + /// RefreshDROPPED. Immutable items do not change, so Refresh is meaningless. /// - /// Note that, because transformation is purely deterministic, Refresh operations are transparently ignored by this operator. + /// Use this when items are immutable, the factory is pure, and the factory is cheap. If any of these conditions are false, use instead. /// + /// or is null. public static IObservable> TransformImmutable( this IObservable> source, Func transformFactory) @@ -4986,67 +5576,55 @@ public static IObservable> TransformImmutable - /// Equivalent to a select many transform. To work, the key must individually identify each child. + /// Flattens each source item into zero or more destination items (1:N), producing a single flat changeset. + /// Each child item must have a globally unique key across all parents. /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// A Will select a enumerable of values. - /// A key selector which must be unique across all. + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. + /// Extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. + /// An observable changeset of flattened child items. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls , emits Add for each child. + /// UpdateDiffs old children vs new children: emits Remove for removed children, Add for new children, Update for children with matching keys. + /// RemoveEmits Remove for all children of the removed parent. + /// RefreshPropagated as Refresh to all children (no re-expansion). + /// + /// Worth noting: If two source items produce children with the same key, last-in-wins. Refresh does NOT re-expand children (only Update does). + /// If two parents produce children with the same key, last-in-wins. Use the async variant with a to control conflict resolution. + /// + /// , , or is null. + /// public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable collection, and subsequently observe observable collection changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// A Will select a enumerable of values. - /// A key selector which must be unique across all. + /// + /// This overload accepts an selector. Changes to the child collection (adds, removes, replacements) are automatically observed and reflected downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable collection, and subsequently observe observable collection changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// A Will select a enumerable of values. - /// A key selector which must be unique across all. + /// + /// This overload accepts a selector. Changes to the child collection are automatically observed and reflected downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull where TSource : notnull where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); - /// - /// Flatten the nested observable cache, and subsequently observe observable cache changes. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// A Will select an observable cache of values. - /// A key selector which must be unique across all. + /// + /// This overload accepts an selector. The child cache is live: subsequent changes to it are automatically propagated downstream. public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull @@ -5054,19 +5632,31 @@ public static IObservable> TransformMa where TSourceKey : notnull => new TransformMany(source, manySelector, keySelector).Run(); /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. + /// Async version of . + /// Flattens each source item into zero or more destination items using an async factory. /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source of . - /// Async function to transform a and into an of . - /// A key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// An async function that expands a parent item (and its key) into an of children. + /// Extracts a unique key from each child item. + /// Optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. + /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. + /// An observable changeset of flattened child items. + /// + /// + /// Because each parent's expansion is async, child collections may arrive via separate changesets + /// (unlike the synchronous TransformMany which batches all children into one changeset). + /// + /// + /// Factory exceptions propagate as . Use + /// + /// to catch errors without killing the stream. + /// + /// + /// or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5080,20 +5670,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source of . - /// Async function to transform a into an of . - /// A key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload takes a factory that receives only the source item (without the key). [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5102,21 +5680,8 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a and into an of . - /// A key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5131,21 +5696,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a into an of . - /// A key selector which must be unique across all. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5155,19 +5707,8 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManyAsync((val, _) => manySelector(val), keySelector, equalityComparer, comparer); - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a and into an of . - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live: its changes propagate downstream. No keySelector is needed since the cache already has keys. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5181,19 +5722,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer).Run(); } - /// - /// Extension method similar to except that it allows the tranformation function to be an async method. Also supports comparison and sorting to prioritize values the same destination key returned from multiple sources. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a and into an of . - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5203,20 +5733,23 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManyAsync((val, _) => manySelector(val), equalityComparer, comparer); /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source of . - /// Async function to transform a and into an of . - /// A key selector which must be unique across all. - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// Async version of + /// with error handling. Factory exceptions are caught and routed to instead of + /// terminating the stream. + /// + /// The type of the child items. + /// The type of the child item keys. + /// The type of the source (parent) items. + /// The type of the source (parent) keys. + /// The source changeset of parent items. + /// An async function that expands a parent item (and its key) into an of children. + /// Extracts a unique key from each child item. + /// Called when throws. The faulting item is skipped and the stream continues. + /// Optional comparer to determine if two child items with the same key are equal. + /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. + /// An observable changeset of flattened child items. + /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. + /// , , or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5231,21 +5764,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable changeset with the transformed values. - /// The source of . - /// Async function to transform a into an of . - /// A key selector which must be unique across all. - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload takes a factory that receives only the source item (without the key). [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5254,22 +5774,8 @@ public static IObservable> TransformMa where TSource : notnull where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a and into an of . - /// A key selector which must be unique across all. - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5285,22 +5791,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector, keySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// The type of an observable collection of . - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a into an of . - /// A key selector which must be unique across all. - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an observable collection (of type implementing both and ) whose changes are tracked live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5310,20 +5802,8 @@ public static IObservable> TransformMa where TSourceKey : notnull where TCollection : INotifyCollectionChanged, IEnumerable => source.TransformManySafeAsync((val, _) => manySelector(val), keySelector, errorHandler, equalityComparer, comparer); - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a and into an of . - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives the source item and its key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5338,20 +5818,8 @@ public static IObservable> TransformMa return new TransformManyAsync(source, CreateChangeSetTransformer(manySelector), equalityComparer, comparer, errorHandler).Run(); } - /// - /// Extension method similar to except it accepts an error handler so that failed transformations are not fatal errors. - /// - /// The type of the destination. - /// The type of the destination key. - /// The type of the source. - /// The type of the source key. - /// An observable with the transformed change set. - /// The source of . - /// Async function to transform a into an of . - /// An Callback function for handling an errors. - /// Optional instance to determine if two elements are the same. - /// Optional instance to determine which element to emit if the same key is emitted from multiple child changesets. - /// Because the transformations are asynchronous, unlike TransformMany, each sub-collection could be emitted via a separate changeset. + /// + /// This overload returns an per parent. The child cache is live. The factory receives only the source item. [MethodImpl(MethodImplOptions.AggressiveInlining)] [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -5361,19 +5829,48 @@ public static IObservable> TransformMa where TSourceKey : notnull => source.TransformManySafeAsync((val, _) => manySelector(val), errorHandler, equalityComparer, comparer); /// - /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. + /// Projects each item into a per-item observable. The latest value emitted by each item's observable + /// becomes the transformed value in the output changeset. /// - /// The type of the source changeset. + /// The type of the source items. /// The type of the key. - /// The type of the destination changeset. - /// The source of . Changeset observable. - /// A Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. - /// - /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The source changeset observable. + /// A function that, given a source item and its key, returns an whose emissions become the transformed values. + /// An observable changeset where each key's value is the latest emission from its per-item observable. + /// + /// + /// Source changeset handling (parent events): + /// + /// + /// EventBehavior + /// AddCalls and subscribes to the returned observable. The item is not visible downstream until the observable emits its first value. + /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. The item disappears from downstream until the new observable emits. + /// RemoveDisposes the item's observable subscription. If the item was visible downstream, a Remove is emitted. + /// RefreshForwarded as Refresh if the item is currently visible downstream. Otherwise dropped. + /// + /// + /// Per-item observable handling (transform observable events): + /// + /// + /// EmissionBehavior + /// First valueThe transformed item appears downstream as an Add. + /// Subsequent valuesEach new value replaces the previous one: an Update is emitted downstream. + /// ErrorTerminates the entire output stream. + /// CompletedThe item remains at its last emitted value. No further updates are possible for this item. + /// + /// + /// Worth noting: Items are invisible downstream until their per-item observable emits at least one value. + /// If an item's observable never emits, that item never appears in the output. The transform factory's selector + /// runs under an internal lock, so it must not synchronously access other DynamicData caches (deadlock risk in + /// cross-cache pipelines). The output completes when the source completes and all per-item observables have + /// also completed. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5385,18 +5882,8 @@ public static IObservable> TransformOnObservable< return new TransformOnObservable(source, transformFactory).Run(); } - /// - /// Transforms each item in the ChangeSet into an Observable that provides the value for the Resulting ChangeSet. - /// - /// The type of the source changeset. - /// The type of the key. - /// The type of the destination changeset. - /// The source of . Changeset observable. - /// A Factory function to create the Observable that will provide the values in the result changeset from the given object in the source changeset. - /// - /// A changeset whose value for a given key is the latest value emitted from the transformed Observable and will update to future values from that observable. - /// - /// source or transformFactory. + /// + /// This overload takes a factory that receives only the source item (without the key). public static IObservable> TransformOnObservable(this IObservable> source, Func> transformFactory) where TSource : notnull where TKey : notnull @@ -5407,23 +5894,8 @@ public static IObservable> TransformOnObservable< return source.TransformOnObservable((obj, _) => transformFactory(obj)); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a simpler factory that receives only the current item, and a forceTransform predicate filtering by source item only. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5436,23 +5908,8 @@ public static IObservable> TransformSafe transformFactory(current), errorHandler, forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts a factory that receives the current item and key. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5466,22 +5923,26 @@ public static IObservable> TransformSafe - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. + /// Projects each item using a synchronous factory, catching factory exceptions via a mandatory error handler + /// instead of terminating the stream. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. + /// An observable changeset of transformed items. + /// + /// + /// Behaves identically to + /// except that factory exceptions are routed to instead of propagating as . + /// Source-level errors (i.e. the source observable itself erroring) still propagate normally. + /// + /// Worth noting: Factory exceptions are caught per-item; the faulting item is skipped and reported to the error handler while the stream continues. Source-level errors still terminate the stream. + /// + /// , , or is null. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5498,45 +5959,15 @@ public static IObservable> TransformSafe(source, transformFactory, errorHandler).Run(); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of Invoke to force a new transform for all items. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. The factory receives only the current item. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull where TKey : notnull => source.TransformSafe((cur, _, _) => transformFactory(cur), errorHandler, forceTransform.ForForced()); - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. The factory receives the current item and key. public static IObservable> TransformSafe(this IObservable> source, Func transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5549,23 +5980,8 @@ public static IObservable> TransformSafe transformFactory(cur, key), errorHandler, forceTransform.ForForced()); } - /// - /// Projects each update item to a new form using the specified transform function, - /// providing an error handling action to safely handle transform errors without killing the stream. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Provides the option to safely handle errors without killing the stream. - /// An of Invoke to force a new transform for all items.# - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts of to force re-transformation of ALL items. public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable forceTransform) where TDestination : notnull where TSource : notnull @@ -5578,22 +5994,8 @@ public static IObservable> TransformSafe()); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5607,22 +6009,8 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, forceTransform); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload takes a factory that receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5637,21 +6025,19 @@ public static IObservable> TransformSafeAsync - /// Projects each update item to a new form using the specified transform function. + /// Async version of . + /// Projects each item using an async factory, catching factory exceptions via a mandatory error handler. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// An of . Invoke to force a new transform for items matching the selected objects. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// An async function that produces a . + /// Called when throws or faults. The item is skipped and the stream continues. + /// Optional observable to force re-transformation of matching items. + /// An observable changeset of transformed items. + /// Combines the async execution model of with the error-safe behavior of . + /// , , or is null. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -5665,22 +6051,8 @@ public static IObservable> TransformSafeAsync(source, transformFactory, errorHandler, forceTransform).Run(); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// The Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives only the current item. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5694,22 +6066,8 @@ public static IObservable> TransformSafeAsync transformFactory(current), errorHandler, options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// The Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. The factory receives the current item and key. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5723,22 +6081,8 @@ public static IObservable> TransformSafeAsync transformFactory(current, key), errorHandler, options); } - /// - /// Projects each update item to a new form using the specified transform function. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An error handler. - /// The Additional transform options. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload accepts to control concurrency and Refresh handling. [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, TransformAsyncOptions options) where TDestination : notnull @@ -5753,14 +6097,27 @@ public static IObservable> TransformSafeAsync - /// Transforms the object to a fully recursive tree, create a hierarchy based on the pivot function. + /// Builds a hierarchical tree from a flat changeset using a parent key selector. + /// Each item becomes a with Parent, Children, Depth, and IsRoot properties. /// - /// The type of the object. + /// The type of the source items. Must be a reference type. /// The type of the key. - /// The source of . - /// A pivot on. - /// An of . Observable to change the underlying predicate. - /// An observable which will emit change sets. + /// The source changeset of flat items. + /// A function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. + /// Optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. + /// An observable changeset of items representing the tree. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCreates node, attaches to parent (or root if parent not found), emits Add. + /// UpdateUpdates node. If returns a different parent key, the node is re-parented. + /// RemoveRemoves node. Orphaned children become root nodes. + /// RefreshRe-evaluates parent key. May re-parent the node if the parent changed. + /// + /// Circular references are NOT detected. If item A is the parent of B and B is the parent of A, behavior is undefined. + /// + /// or is null. public static IObservable, TKey>> TransformToTree(this IObservable> source, Func pivotOn, IObservable, bool>>? predicateChanged = null) where TObject : class where TKey : notnull @@ -5771,21 +6128,8 @@ public static IObservable, TKey>> TransformToTree return new TreeBuilder(source, pivotOn, predicateChanged).Run(); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload defaults to transformOnRefresh: false and does not provide an error handler (factory exceptions propagate as OnError). public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction) where TDestination : class where TSource : notnull @@ -5798,22 +6142,8 @@ public static IObservable> TransformWithInlineUpd return source.TransformWithInlineUpdate(transformFactory, updateAction, false); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload does not provide an error handler (factory exceptions propagate as OnError). The transformOnRefresh parameter controls Refresh behavior. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -5826,22 +6156,8 @@ public static IObservable> TransformWithInlineUpd return new TransformWithInlineUpdate(source, transformFactory, updateAction, transformOnRefresh: transformOnRefresh).Run(); } - /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. - /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// An error handler. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// + /// This overload defaults to transformOnRefresh: false but includes an error handler for factory/update action exceptions. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler) where TDestination : class where TSource : notnull @@ -5856,22 +6172,33 @@ public static IObservable> TransformWithInlineUpd } /// - /// Projects each update item to a new form using the specified transform function and when an update is received, allows the preservation of the previous instance. + /// Projects each item using a transform factory for Add, and mutates the existing transformed + /// item in place (via an update action) for Update, preserving the original object reference. /// - /// The type of the destination. - /// The type of the source. - /// The type of the key. - /// The source of . - /// A transform factory. - /// An Apply changes to the original. Example (previousTransformedItem, newOriginalItem) => previousTransformedItem.Value = newOriginalItem. - /// An error handler. - /// Should a new transform be applied when a refresh event is received. - /// - /// A transformed update collection. - /// - /// source - /// or - /// transformFactory. + /// The type of the transformed items. Must be a reference type since items are mutated in place. + /// The type of the source items. + /// The type of the key. + /// The source changeset observable. + /// Called on Add (and optionally Refresh) to create a new . + /// Called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. + /// Called when or throws. The faulting item is skipped. + /// When true, Refresh changes call on the existing item. + /// An observable changeset of transformed items. + /// + /// + /// This is useful when the destination type is a ViewModel that should maintain its identity across updates. + /// Instead of replacing the entire ViewModel, the update action patches the existing instance. + /// + /// Change reason handling: + /// + /// Input reasonOutput behavior + /// AddCalls , emits Add. + /// UpdateCalls on the EXISTING transformed item (same reference), emits Update. + /// RemoveEmits Remove. + /// RefreshIf is true, calls . Otherwise forwarded as Refresh. + /// + /// + /// , , , or is null. public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -5890,7 +6217,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source changeset stream. /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -5919,23 +6246,30 @@ static IEnumerable> ReplaceMoves(IChangeSet } /// - /// - /// Produces a boolean observable indicating whether the latest resulting value from all of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever. - /// - /// - /// i) The cache changes - /// or ii) The inner observable changes. - /// + /// Emits true when all items in the cache satisfy a condition based on their per-item observable, + /// and false otherwise. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. - /// The type of the value. - /// The source of . - /// A Selector which returns the target observable. - /// A equality condition. - /// An observable which boolean values indicating if true. - /// source. + /// The type of the value emitted by each per-item observable. + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each per-item observable's latest value. + /// An observable of bool that emits whenever the all-items condition changes. + /// , , or is null. + /// + /// + /// EventBehavior + /// AddA new per-item subscription is created. The aggregate condition is recalculated. + /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. + /// RemovePer-item subscription disposed. Condition recalculated over remaining items. + /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. + /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. + /// OnCompletedCompletes when the source and all per-item observables have completed. + /// + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache is vacuously true. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// + /// public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -5954,9 +6288,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// The source of . - /// A Selector which returns the target observable. - /// A equality condition. + /// The source changeset stream. + /// Selector which returns the target observable. + /// The equality condition. /// An observable which boolean values indicating if true. /// source. public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -5965,50 +6299,40 @@ public static IObservable TrueForAll(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.All(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever - /// i) The cache changes. - /// or ii) The inner observable changes. + /// Emits true when any item in the cache satisfies a condition based on its per-item observable, + /// and false when none do. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. - /// The type of the value. - /// The source of . - /// A observable selector. - /// A equality condition. - /// An observable which boolean values indicating if true. - /// - /// source - /// or - /// observableSelector - /// or - /// equalityCondition. - /// + /// The type of the value emitted by each per-item observable. + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each item and its per-item observable's latest value. + /// An observable of bool that emits whenever the any-item condition changes. + /// , , or is null. + /// + /// + /// EventBehavior + /// AddA new per-item subscription is created. The aggregate condition is recalculated. + /// UpdateThe item is replaced in the collection snapshot. Condition recalculated. + /// RemovePer-item subscription disposed. Condition recalculated over remaining items. + /// RefreshNo effect on per-item subscriptions. Condition not recalculated unless the per-item observable emits. + /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. + /// OnCompletedCompletes when the source and all per-item observables have completed. + /// + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache yields false. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// + /// public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); - /// - /// Produces a boolean observable indicating whether the resulting value of whether any of the specified observables matches - /// the equality condition. The observable is re-evaluated whenever - /// i) The cache changes. - /// or ii) The inner observable changes. - /// - /// The type of the object. - /// The type of the key. - /// The type of the value. - /// The source of . - /// A observable selector. - /// A equality condition. - /// An observable which boolean values indicating if true. - /// - /// source - /// or - /// observableSelector - /// or - /// equalityCondition. - /// + /// + /// The source changeset stream. + /// Factory that produces a condition observable for each item. + /// Predicate applied to each per-item observable's latest value (without the item). + /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull where TKey : notnull @@ -6022,24 +6346,36 @@ public static IObservable TrueForAny(this IObservab } /// - /// Updates the index for an object which implements IIndexAware. + /// Sets the Index property on each item (which must implement ) + /// to reflect its position in the sorted output. Operates on . /// /// The type of the object. /// The type of the key. - /// The source of . - /// An observable which emits the sorted change set. + /// The source sorted changeset stream. + /// An observable that emits the sorted changesets after updating item indices. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware where TKey : notnull => source.Do(changes => changes.SortedItems.Select((update, index) => new { update, index }).ForEach(u => u.update.Value.Index = u.index)); /// - /// Returns an observable of any updates which match the specified key, proceeded with the initial cache state. + /// Filters the source changeset stream to a single key, emitting each for that key. + /// Changes for all other keys are ignored. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The key. - /// An observable which emits the change. + /// The source changeset stream. + /// The key to observe. + /// An observable of for the specified key only. + /// + /// + /// Emits Add, Update, Remove, and Refresh changes as they occur for the target key. + /// No initial emission occurs if the key is not yet present in the cache. This operator does not + /// produce changesets; it produces individual change notifications. For Optional-based watching, + /// use . + /// + /// + /// + /// public static IObservable> Watch(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6050,14 +6386,33 @@ public static IObservable> Watch(this IObse } /// - /// Watches updates for a single value matching the specified key. + /// Filters the source changeset stream to a single key, emitting the current value each time it changes. + /// Even emits the value on removal (the removed item's value). /// /// The type of the object. /// The type of the key. - /// The source. - /// The key. - /// An observable which emits the object value. - /// source. + /// The source changeset stream. + /// The key to observe. + /// An observable of the item's value whenever it changes for the specified key. + /// + /// + /// Unlike , + /// this does not emit Optional.None on removal. It emits the removed item's value instead. + /// If you need to distinguish presence from absence, use ToObservableOptional. + /// + /// + /// EventBehavior + /// AddEmits the added item's value. + /// UpdateEmits the new value. + /// RemoveEmits the removed item's value (not None; use if you need removal detection). + /// RefreshEmits the current value. + /// OnErrorForwarded to the downstream observer. + /// OnCompletedForwarded to the downstream observer. + /// + /// Worth noting: No emission occurs if the key is not present at subscription time. Changes to other keys are ignored entirely. + /// + /// + /// public static IObservable WatchValue(this IObservableCache source, TKey key) where TObject : notnull where TKey : notnull @@ -6067,15 +6422,10 @@ public static IObservable WatchValue(this IObservableCac return source.Watch(key).Select(u => u.Current); } - /// - /// Watches updates for a single value matching the specified key. - /// - /// The type of the object. - /// The type of the key. - /// The source of . - /// The key. - /// An observable which emits the object value. - /// source. + /// + /// The source changeset stream. + /// The key to observe. + /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) where TObject : notnull where TKey : notnull @@ -6086,13 +6436,34 @@ public static IObservable WatchValue(this IObservable - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits an item whenever any of its properties change via . + /// Subscribes to PropertyChanged on each cache item using MergeMany. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The source of . - /// specify properties to Monitor, or omit to monitor all property changes. - /// An observable which emits the object which has had a property changed. + /// The source changeset stream. + /// Specific property names to monitor. If empty, all property changes trigger emissions. + /// An observable that emits the item itself each time a monitored property changes. + /// + /// + /// Subscriptions are managed per item: created on Add, replaced on Update, disposed on Remove. + /// Errors from individual property subscriptions are silently ignored. The output is not a changeset + /// stream; it is a plain IObservable<TObject?>. If the same item changes multiple properties + /// rapidly, each change emits the item separately (no deduplication). + /// + /// + /// EventBehavior + /// AddSubscribes to PropertyChanged on the new item. + /// UpdateDisposes the old item's subscription and subscribes to the new item. + /// RemoveDisposes the item's PropertyChanged subscription. + /// RefreshNo effect on subscriptions. + /// OnErrorErrors from individual property subscriptions are silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source changeset stream completes. + /// + /// + /// + /// + /// public static IObservable WhenAnyPropertyChanged(this IObservable> source, params string[] propertiesToMonitor) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6103,15 +6474,32 @@ public static IObservable WatchValue(this IObservable - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits a (item + property value) whenever the specified property + /// changes on any item in the cache. Subscribes via using MergeMany. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The type of the value. - /// The source of . - /// An property accessor. - /// If true the resulting observable includes the initial value. - /// An observable which emits a property when it has changed. + /// The type of the monitored property. + /// The source changeset stream. + /// Expression selecting the property to monitor. + /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// An observable of containing both the item and its property value. + /// + /// + /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual + /// property subscriptions are silently ignored. The output is not a changeset stream. If you only need + /// the value (not the owning item), use instead. + /// + /// + /// EventBehavior + /// AddSubscribes to the specified property on the new item. If notifyOnInitialValue is true, the current value is emitted immediately. + /// UpdateDisposes the old item's property subscription and subscribes to the new item. + /// RemoveDisposes the item's property subscription. No further emissions for this item. + /// RefreshNo effect on subscriptions. The existing property subscription continues. + /// OnErrorPer-item property subscription errors are silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source changeset stream completes. + /// + /// public static IObservable> WhenPropertyChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6123,15 +6511,35 @@ public static IObservable> WhenPropertyChanged - /// Watches each item in the collection and notifies when any of them has changed. + /// Emits the property value whenever the specified property changes on any item in the cache. + /// Like but emits only the value, discarding the owning item. /// - /// The type of the object. + /// The type of the object (must implement ). /// The type of the key. - /// The type of the value. - /// The source of . - /// An property accessor. - /// If true the resulting observable includes the initial value. - /// An observable which emits a value when it has changed. + /// The type of the monitored property. + /// The source changeset stream. + /// Expression selecting the property to monitor. + /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// An observable of property values. The owning item is not included; use if you need it. + /// + /// + /// Per-item subscriptions are created on Add, replaced on Update, disposed on Remove. Errors from individual + /// property subscriptions are silently ignored. If you need to correlate a value back to its source item, + /// use which returns a pair. + /// + /// + /// EventBehavior + /// AddSubscribes to the specified property. If notifyOnInitialValue is true, the current value is emitted immediately. + /// UpdateDisposes the old subscription, subscribes to the new item's property. + /// RemoveDisposes the property subscription. + /// RefreshNo effect on subscriptions. + /// OnErrorPer-item errors silently ignored. Source errors terminate the stream. + /// OnCompletedCompletes when the source completes. + /// + /// + /// + /// + /// public static IObservable WhenValueChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6147,11 +6555,14 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// The source of . - /// The values reasons. + /// The source changeset stream. + /// The reasons. /// An observable which emits a change set with items matching the reasons. /// reasons. /// Must select at least on reason. + /// + /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. + /// public static IObservable> WhereReasonsAre(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6174,11 +6585,14 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// The source of . - /// The values reasons. + /// The source changeset stream. + /// The reasons. /// An observable which emits a change set with items not matching the reasons. /// reasons. /// Must select at least on reason. + /// + /// Worth noting: Filtering out Remove changes will cause memory leaks in downstream caches, since items are never cleaned up. + /// public static IObservable> WhereReasonsAreNot(this IObservable> source, params ChangeReason[] reasons) where TObject : notnull where TKey : notnull @@ -6196,19 +6610,34 @@ public static IObservable> WhereReasonsAreNot - /// Apply a logical Xor operator between the collections. - /// Items which are only in one of the sources are included in the result. + /// Combines multiple changeset streams using logical XOR (symmetric difference). + /// An item appears downstream only if it exists in exactly one source. /// /// The type of the object. /// The type of the key. - /// The source of . - /// The other of streams. - /// An observable which emits a change set. - /// - /// source - /// or - /// others. - /// + /// The first source changeset stream. + /// Additional changeset streams to combine with. + /// A changeset stream containing items present in exactly one source. + /// + /// + /// Items are tracked via reference counting. An item appears downstream only when exactly one + /// source holds it. Adding the same key from a second source removes it from the result; + /// removing from that second source restores it. + /// + /// + /// EventBehavior + /// AddIf the key is now held by exactly one source, an Add is emitted. If adding causes the count to reach 2+, a Remove is emitted (the item is no longer exclusive). + /// UpdateIf the item is currently downstream (count is 1), an Update is emitted. + /// RemoveReference count decremented. If the count drops to exactly 1, an Add is emitted (the item is now exclusive to one source). If it drops to 0, a Remove is emitted. + /// RefreshIf the item is downstream, a Refresh is forwarded. + /// OnErrorAn error from any source terminates the combined output. + /// OnCompletedThe output completes when all sources have completed. + /// + /// + /// or is null. + /// + /// + /// public static IObservable> Xor(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -6223,19 +6652,9 @@ public static IObservable> Xor(this IOb return source.Combine(CombineOperator.Xor, others); } - /// - /// Apply a logical Xor operator between the collections. - /// Items which are only in one of the sources are included in the result. - /// - /// The type of the object. - /// The type of the key. - /// An of of streams. source. - /// An observable which emits a change set. - /// - /// source - /// or - /// others. - /// + /// + /// A fixed collection of changeset streams to combine. + /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Xor(this ICollection>> sources) where TObject : notnull where TKey : notnull @@ -6251,7 +6670,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// An of of streams. source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull @@ -6268,7 +6687,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull @@ -6285,7 +6704,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// An of instances. source. + /// The source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull From 6d56c5324042c78532c32c7d27b30dfa48d22443 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:20:39 -0700 Subject: [PATCH 12/23] docs: add type links to cache operator param descriptions Surgical param-by-param replacement: each param's type determined from the actual method signature and linked via see/cref. 344/618 params linked in main file, 7/25 in VirtualiseAndPage. All existing event tables, seealso, inheritdoc, and worth-noting sections preserved intact. --- .../ObservableCacheEx.VirtualiseAndPage.cs | 14 +- src/DynamicData/Cache/ObservableCacheEx.cs | 644 +++++++++--------- 2 files changed, 329 insertions(+), 329 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index 325fe8e4e..6aa4caa9b 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -129,8 +129,8 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The virtualising requests. + /// the source changeset stream. + /// the virtualising requests. /// An observable which will emit virtual change sets. /// source. [Obsolete(Constants.VirtualizeIsObsolete)] @@ -150,8 +150,8 @@ public static IObservable> Virtualise /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer. + /// the source changeset stream. + /// the comparer. /// The maximum number of items to return. /// An observable which will emit virtual change sets. /// source. @@ -184,7 +184,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The size. /// An observable which will emit virtual change sets. /// source. @@ -319,8 +319,8 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The page requests. + /// the source changeset stream. + /// the page requests. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] public static IObservable> Page(this IObservable> source, IObservable pageRequests) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 119cb44aa..b92abe8ea 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -65,7 +65,7 @@ public static IObservable> Adapt(this I } /// - /// The source sorted changeset stream. + /// the source sorted changeset stream. /// The sorted adaptor whose Adapt method is called for each sorted changeset. /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) @@ -84,7 +84,7 @@ public static IObservable> Adapt(this I /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// The item to add or update. /// /// Convenience method that wraps a single-item mutation inside . @@ -111,7 +111,7 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The source cache. + /// the source cache. /// The item to add or update. /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// This overload uses to suppress no-op updates when the new value equals the existing one. @@ -125,8 +125,8 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The source cache. - /// The items to add or update. + /// the source cache. + /// the items to add or update. /// Batch overload. All items are added/updated inside a single call, producing one changeset. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -138,8 +138,8 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The source cache. - /// The items to add or update. + /// the source cache. + /// the items to add or update. /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) @@ -152,7 +152,7 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The source intermediate cache. + /// the source intermediate cache. /// The item to add or update. /// The key to associate with the item. /// This overload operates on , which requires an explicit key parameter. @@ -172,7 +172,7 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The others. /// An observable which emits change sets. /// source or others. @@ -231,7 +231,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -248,7 +248,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -264,7 +264,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source cache to wrap. + /// the source cache to wrap. /// A read-only . /// is null. /// @@ -283,7 +283,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// If true (default), all cache operations are synchronized. Set to false when the caller guarantees single-threaded access. /// A read-only observable cache that reflects the current state of the pipeline. /// @@ -370,10 +370,10 @@ public static IObservable> AsyncDisposeMany /// The object of the change set. /// The key of the change set. - /// The source observable. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// the source observable. + /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// A optional when observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// An optional the scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -401,11 +401,11 @@ public static IObservable> AutoRefresh( /// The object of the change set. /// The key of the change set. /// The type of the property. - /// The source observable. - /// Specify a property to observe changes. When it changes a Refresh is invoked. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// When observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. - /// The scheduler. + /// the source observable. + /// A that specify a property to observe changes. When it changes a Refresh is invoked. + /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. + /// A optional when observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// An optional the scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, Expression> propertyAccessor, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -433,10 +433,10 @@ public static IObservable> AutoRefreshThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source observable change set. - /// An observable which acts on items within the collection and produces a value when the item should be refreshed. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// the source observable change set. + /// an observable which acts on items within the collection and produces a value when the item should be refreshed. + /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// An optional the scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull @@ -448,10 +448,10 @@ public static IObservable> AutoRefreshOnObservableThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source observable change set. - /// An observable which acts on items within the collection and produces a value when the item should be refreshed. - /// Batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. - /// The scheduler. + /// the source observable change set. + /// an observable which acts on items within the collection and produces a value when the item should be refreshed. + /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// An optional the scheduler. /// An observable change set with additional refresh changes. /// /// Worth noting: Per-item observable errors are silently ignored (not forwarded to the downstream observer). Only source stream errors propagate. @@ -564,11 +564,11 @@ public static IObservable> BatchIf(this } /// - /// The source changeset stream. - /// When true, buffering begins. When false, the buffer is flushed. + /// the source changeset stream. + /// An that when true, buffering begins. When false, the buffer is flushed. /// If true, starts in a paused (buffering) state. - /// An observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. - /// The scheduler. + /// An optional an observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. + /// An optional the scheduler. /// This overload accepts an explicit timer observable instead of a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IObservable? timer = null, IScheduler? scheduler = null) where TObject : notnull @@ -579,8 +579,8 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// the source changeset stream. + /// the destination. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. /// source. @@ -606,8 +606,8 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// the source changeset stream. + /// the destination. /// The binding options. /// An observable which will emit change sets. /// source. @@ -625,9 +625,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. - /// The updater. + /// the source changeset stream. + /// the destination. + /// the updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, IObservableCollectionAdaptor updater) @@ -656,7 +656,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The resulting read only observable collection. /// The binding options. /// An observable which will emit change sets. @@ -677,11 +677,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The resulting read only observable collection. /// The number of changes before a reset notification is triggered. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// Specify an adaptor to change the algorithm to update the target collection. + /// An optional specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, IObservableCollectionAdaptor? adaptor = null) @@ -713,8 +713,8 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// the source changeset stream. + /// the destination. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination) @@ -732,8 +732,8 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// the source changeset stream. + /// the destination. /// The binding options. /// An observable which will emit change sets. /// source. @@ -753,8 +753,8 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The destination. + /// the source changeset stream. + /// the destination. /// The updater. /// An observable which will emit change sets. /// source. @@ -784,7 +784,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The resulting read only observable collection. /// The binding options. /// An observable which will emit change sets. @@ -807,7 +807,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. @@ -841,7 +841,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source changeset stream. + /// the source changeset stream. /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. @@ -865,7 +865,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source changeset stream. + /// the source changeset stream. /// The target binding list. /// The reset threshold. /// An observable which will emit change sets. @@ -892,8 +892,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The type of the key. - /// The source change set. - /// The time window to buffer, measured from when the first changeset arrives. + /// the source change set. + /// the time window to buffer, measured from when the first changeset arrives. /// The scheduler for timing. Defaults to . /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. /// @@ -923,8 +923,8 @@ public static IObservable> BufferInitialThe type of the source object. /// The type of the key. /// The type of the destination object. - /// The source changeset stream. - /// The conversion function applied to each item. + /// the source changeset stream. + /// the conversion function applied to each item. /// An observable changeset of converted items. /// /// @@ -955,8 +955,8 @@ public static IObservable> CastThe type of the object. /// The type of the source key. /// The type of the destination key. - /// The source changeset stream. - /// A function that computes the destination key from the item, e.g. (item) => item.NewId. + /// the source changeset stream. + /// a function that computes the destination key from the item, e.g. (item) => item.NewId. /// An observable changeset with items re-keyed using . /// /// @@ -1012,7 +1012,7 @@ public static IObservable> ChangeKey /// The type of the object. /// The type of the key. - /// The source cache to clear. + /// the source cache to clear. /// /// /// EventBehavior @@ -1059,8 +1059,8 @@ public static void Clear(this LockFreeObservableCache /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The target collection to which changes are applied. + /// the source changeset stream. + /// the target collection to which changes are applied. /// An observable that forwards all changesets from unchanged. /// /// @@ -1116,8 +1116,8 @@ public static IObservable> Clone(this I /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source changeset stream. - /// The conversion factory. + /// the source changeset stream. + /// the conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] public static IObservable> Convert(this IObservable> source, Func conversionFactory) @@ -1142,7 +1142,7 @@ public static IObservable> Convert /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable that begins emitting changesets once the first non-empty changeset is received. /// /// @@ -1225,8 +1225,8 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// The value selector. + /// the source changeset stream. + /// the value selector. /// An observable which will emit distinct change sets. /// /// Due to it's nature only adds or removes can be returned. @@ -1245,8 +1245,8 @@ public static IObservable> DistinctValues - /// The source cache to diff against. - /// The complete snapshot of items to diff against the cache. + /// the source cache to diff against. + /// the complete snapshot of items to diff against the cache. /// An used to determine whether a new item is the same as an existing cached item. /// /// This overload uses an instead of a delegate @@ -1269,9 +1269,9 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// The source cache to diff against. - /// The complete snapshot of desired items. - /// A function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// the source cache to diff against. + /// the complete snapshot of desired items. + /// a function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. /// /// /// EventBehavior @@ -1303,8 +1303,8 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// The source observable of item snapshots. - /// A function to extract the unique key from each item. + /// the source observable of item snapshots. + /// a function to extract the unique key from each item. /// Optional for comparing items. Uses default equality if null. /// An observable changeset representing the incremental differences between successive snapshots. /// @@ -1336,8 +1336,8 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// The source observable of optional values. - /// A function to extract the unique key from each item. + /// the source observable of optional values. + /// a function to extract the unique key from each item. /// Optional for comparing items. Uses default equality if null. /// An observable changeset tracking the single optional item. /// @@ -1368,7 +1368,7 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// The source changeset stream to validate. + /// the source changeset stream to validate. /// A changeset stream guaranteed to contain unique keys per changeset. /// /// @@ -1396,7 +1396,7 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The others. /// An observable which emits change sets. /// @@ -1463,7 +1463,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1480,7 +1480,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1497,8 +1497,8 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. + /// the source changeset stream. + /// A optional a function returning the expiration timeout for each item, or null for no expiration. /// An observable changeset that includes timer-driven Remove changes for expired items. /// /// When a timer fires, a Remove is emitted for the expired item. @@ -1524,9 +1524,9 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector); /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// The scheduler used to schedule expiration timers. + /// the source changeset stream. + /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// the scheduler used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1539,8 +1539,8 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. + /// the source changeset stream. + /// A optional a function returning the expiration timeout for each item, or null for no expiration. /// If specified, items are expired on a polling interval rather than per-item timers. /// This is less accurate but more efficient when many items share similar expiration times. /// @@ -1559,10 +1559,10 @@ public static IObservable> ExpireAfter( pollingInterval: pollingInterval); /// - /// The source changeset stream. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. - /// The scheduler used to schedule polling and expiration timers. + /// the source changeset stream. + /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional if specified, items are expired on a polling interval rather than per-item timers. + /// the scheduler used to schedule polling and expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1582,9 +1582,9 @@ public static IObservable> ExpireAfter( /// /// The type of the object. /// The type of the key. - /// The source cache from which expired items are removed. - /// A function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. + /// the source cache from which expired items are removed. + /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional if specified, items are expired on a polling interval rather than per-item timers. /// The scheduler used to schedule expiration timers. Defaults to if null. /// An observable that emits the key-value pairs of items removed from the cache by expiration. /// @@ -1612,8 +1612,8 @@ public static IObservable>> ExpireAfter< /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The predicate used to determine whether each item is included. + /// the source changeset stream. + /// the predicate used to determine whether each item is included. /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets, which can be useful for monitoring loading status. /// An observable changeset containing only items that satisfy . /// @@ -1702,9 +1702,9 @@ public static IObservable> Filter - /// The source changeset stream. - /// An observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. - /// An observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. + /// the source changeset stream. + /// an observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. + /// an observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. /// When true (default), empty changesets are suppressed for performance. /// /// In addition to the per-item behavior described in the static overload, @@ -1845,8 +1845,8 @@ public static IObservable> FilterOnObservableFinally operator instead. /// /// The type contained within the observables. - /// The source changeset stream. - /// The finally action. + /// the source changeset stream. + /// the finally action. /// An observable which has always a finally action applied. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) @@ -1863,7 +1863,7 @@ public static IObservable FinallySafe(this IObservable source, Action f /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable of individual values. /// is null. /// @@ -1900,7 +1900,7 @@ public static IObservable> FlattenBufferResult /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The action to invoke for each change. Receives the full struct, including , , , and . /// A stream that forwards all changesets from unchanged. /// @@ -1929,9 +1929,9 @@ public static IObservable> ForEachChange - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) @@ -2008,9 +2008,9 @@ public static IObservable> FullJoin - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) @@ -2094,8 +2094,8 @@ public static IObservable> FullJoinManyThe type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The group selector factory. + /// the source changeset stream. + /// the group selector factory. /// /// A distinct stream used to determine the result. /// @@ -2160,9 +2160,9 @@ public static IObservable> Group - /// The source changeset stream. - /// Extracts the group key from each item. - /// When this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. + /// the source changeset stream. + /// A that extracts the group key from each item. + /// An that when this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. /// An observable that emits group changesets. /// This overload adds a signal. When it fires, every item in the cache is re-grouped using the current selector, which is useful when the grouping depends on mutable item state. public static IObservable> Group(this IObservable> source, Func groupSelectorKey, IObservable regrouper) @@ -2218,9 +2218,9 @@ public static IObservable> Group - /// The source changeset stream. - /// An observable of selector functions that take only the item (not the key). - /// Optional signal to force re-evaluation. + /// the source changeset stream. + /// an observable of selector functions that take only the item (not the key). + /// An optional optional signal to force re-evaluation. /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull @@ -2296,8 +2296,8 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The group selector key. + /// the source changeset stream. + /// the group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull @@ -2316,10 +2316,10 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// the source changeset stream. + /// the property selector used to group the items. + /// A optional a time span that indicates the throttle to wait for property change events. + /// An optional the scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnProperty(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2339,10 +2339,10 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// The property selector used to group the items. - /// A time span that indicates the throttle to wait for property change events. - /// The scheduler. + /// the source changeset stream. + /// the property selector used to group the items. + /// A optional a time span that indicates the throttle to wait for property change events. + /// An optional the scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnPropertyWithImmutableState(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2401,7 +2401,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// The source observable which emits change sets. + /// the source observable which emits change sets. /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2413,8 +2413,8 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The ignore function (current,previous)=>{ return true to ignore }. + /// the source changeset stream. + /// the ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) where TObject : notnull @@ -2440,8 +2440,8 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The include function (current,previous)=>{ return true to include }. + /// the source changeset stream. + /// the include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) where TObject : notnull @@ -2459,10 +2459,10 @@ public static IObservable> IncludeUpdateWhen - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the left and right values into a destination object. The composite key is not provided in this overload. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the left and right values into a destination object. The composite key is not provided in this overload. /// Overload that omits the composite key from the result selector. Delegates to . public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func resultSelector) where TLeft : notnull @@ -2538,9 +2538,9 @@ public static IObservable> IncludeUpdateWhen - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2622,7 +2622,7 @@ public static IObservable> InnerJoinMany /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable that emits the same changesets as , unchanged. /// /// @@ -2640,9 +2640,9 @@ public static IObservable> InvokeEvaluate source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the left value and the optional right into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2719,9 +2719,9 @@ public static IObservable> LeftJoin - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2803,7 +2803,7 @@ public static IObservable> LeftJoinMany /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The maximum number of items allowed. Must be greater than zero. /// An observable changeset stream with size-limited contents. /// @@ -2839,7 +2839,7 @@ public static IObservable> LimitSizeTo( /// /// The type of the object. /// The type of the key. - /// The source cache to apply the size limit to. + /// the source cache to apply the size limit to. /// The maximum number of items allowed. Must be greater than zero. /// Optional scheduler for observing changes. Defaults to . /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. @@ -2922,8 +2922,8 @@ public static IObservable MergeMany(t } /// - /// The source cache changeset stream. - /// Factory function that receives both the item and its key, and returns a child observable. + /// the source cache changeset stream. + /// A that factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3060,9 +3060,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . - /// Optional scheduler used when subscribing to the source streams. + /// the first changeset stream. + /// the second changeset stream to merge with . + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. /// or is null. @@ -3081,10 +3081,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . + /// the first changeset stream. + /// the second changeset stream to merge with . /// Comparer to determine which value wins when both sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. @@ -3104,10 +3104,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . + /// the first changeset stream. + /// the second changeset stream to merge with . /// Equality comparer to detect duplicate values for the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. @@ -3127,11 +3127,11 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The first changeset stream. - /// The second changeset stream to merge with . + /// the first changeset stream. + /// the second changeset stream to merge with . /// Equality comparer to detect duplicate values for the same key. /// Comparer to determine which value wins when both sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. /// , , , or is null. @@ -3153,9 +3153,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The primary changeset stream. + /// the primary changeset stream. /// Additional changeset streams to merge with . - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. /// or is null. @@ -3174,10 +3174,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The primary changeset stream. + /// the primary changeset stream. /// Additional changeset streams to merge with . /// Comparer to determine which value wins when multiple sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. @@ -3197,10 +3197,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The primary changeset stream. + /// the primary changeset stream. /// Additional changeset streams to merge with . /// Equality comparer to detect duplicate values for the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. @@ -3220,11 +3220,11 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The primary changeset stream. + /// the primary changeset stream. /// Additional changeset streams to merge with . /// Equality comparer to detect duplicate values for the same key. /// Comparer to determine which value wins when multiple sources provide the same key. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. /// , , , or is null. @@ -3247,7 +3247,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// The collection of changeset streams to merge. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. /// @@ -3280,7 +3280,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// The collection of changeset streams to merge. /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. @@ -3303,7 +3303,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// The collection of changeset streams to merge. /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. @@ -3326,7 +3326,7 @@ public static IObservable> MergeChangeSetsThe collection of changeset streams to merge. /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// Optional scheduler used when subscribing to the source streams. + /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. /// , , or is null. @@ -3350,7 +3350,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3374,7 +3374,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child cache changeset stream. /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3400,7 +3400,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. @@ -3500,7 +3500,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// Fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3527,7 +3527,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// Fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3547,7 +3547,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. @@ -3574,7 +3574,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. @@ -3596,7 +3596,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. /// Optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3623,7 +3623,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. /// Optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3644,7 +3644,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. @@ -3674,7 +3674,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child cache changeset stream. /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. @@ -3713,7 +3713,7 @@ public static IObservable> MergeManyCh /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and its key, and returns a child list changeset stream. /// Optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3735,7 +3735,7 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source cache changeset stream. + /// the source cache changeset stream. /// Factory function that receives a source item and returns a child list changeset stream. /// Optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3756,8 +3756,8 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source cache changeset stream. - /// Factory function that produces a child observable for each source item. + /// the source cache changeset stream. + /// A that factory function that produces a child observable for each source item. /// An observable of pairing each emission with its source item. /// or is null. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) @@ -3771,8 +3771,8 @@ public static IObservable> MergeManyItems - /// The source cache changeset stream. - /// Factory function that receives both the item and its key, and returns a child observable. + /// the source cache changeset stream. + /// A that factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3789,7 +3789,7 @@ public static IObservable> MergeManyItems /// The type of the source observable. - /// The source observable to monitor. + /// the source observable to monitor. /// An observable that emits values reflecting the source's lifecycle. /// is null. /// @@ -3800,7 +3800,7 @@ public static IObservable> MergeManyItems /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable that emits only non-empty changesets. /// is null. /// @@ -3820,7 +3820,7 @@ public static IObservable> NotEmpty(thi /// The type of the objects in the source changeset. /// The type of the key. /// The destination type to filter and cast to. - /// The source observable changeset. + /// the source observable changeset. /// If true, changesets that become empty after filtering are suppressed. /// An observable changeset of items. /// @@ -3883,8 +3883,8 @@ public static IObservable> OnItemAdded( } /// - /// The source changeset stream. - /// The callback invoked for each added item. Receives only the item (no key). + /// the source changeset stream. + /// the callback invoked for each added item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull @@ -3897,7 +3897,7 @@ public static IObservable> OnItemAdded( /// The type of the object. /// The type of the key. /// The source changeset stream. - /// The callback invoked for each refreshed item. Receives the item and its key. + /// the callback invoked for each refreshed item. Receives the item and its key. /// A stream that forwards all changesets from unchanged. /// /// @@ -3927,8 +3927,8 @@ public static IObservable> OnItemRefreshed - /// The source changeset stream. - /// The callback invoked for each refreshed item. Receives only the item (no key). + /// the source changeset stream. + /// the callback invoked for each refreshed item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull @@ -3990,8 +3990,8 @@ public static IObservable> OnItemRemoved - /// The source changeset stream. - /// The callback invoked for each removed item. Receives only the item (no key). + /// the source changeset stream. + /// the callback invoked for each removed item. Receives only the item (no key). /// When true (the default), also invoked for all remaining items on disposal. /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) @@ -4037,8 +4037,8 @@ public static IObservable> OnItemUpdated - /// The source changeset stream. - /// The callback invoked for each updated item. Receives only the current and previous values (no key). + /// the source changeset stream. + /// the callback invoked for each updated item. Receives only the current and previous values (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull @@ -4122,7 +4122,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4139,7 +4139,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4155,8 +4155,8 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// The source cache to populate. - /// The observable that emits batches of items. + /// the source cache to populate. + /// the observable that emits batches of items. /// An that, when disposed, unsubscribes from . /// /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. @@ -4178,8 +4178,8 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// The source cache to populate. - /// The observable that emits individual items. + /// the source cache to populate. + /// the observable that emits individual items. /// An that, when disposed, unsubscribes from . /// or is null. public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) @@ -4197,7 +4197,7 @@ public static IDisposable PopulateFrom(this ISourceCacheThe type of the object. /// The type of the key. /// The source changeset stream. - /// The destination cache to populate. + /// the destination cache to populate. /// An that, when disposed, unsubscribes from the source. /// /// @@ -4227,8 +4227,8 @@ public static IDisposable PopulateInto(this IObservable - /// The source changeset stream. - /// The destination intermediate cache to populate. + /// the source changeset stream. + /// the destination intermediate cache to populate. /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) where TObject : notnull @@ -4241,8 +4241,8 @@ public static IDisposable PopulateInto(this IObservable - /// The source changeset stream. - /// The destination lock-free cache to populate. + /// the source changeset stream. + /// the destination lock-free cache to populate. /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) where TObject : notnull @@ -4261,7 +4261,7 @@ public static IDisposable PopulateInto(this IObservableThe type of the object. /// The type of the key. /// The type of the destination. - /// The source changeset stream. + /// the source changeset stream. /// Projects the current snapshot to a result value. /// An observable that emits a projected value after each changeset. /// @@ -4294,7 +4294,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -4312,8 +4312,8 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// Should the query be triggered for observables on individual items. + /// the source changeset stream. + /// A that should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source, Func> itemChangedTrigger) @@ -4332,7 +4332,7 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// A ref-counted observable changeset stream. /// public static IObservable> RefCount(this IObservable> source) @@ -4349,7 +4349,7 @@ public static IObservable> RefCount(thi /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// The item to refresh. /// /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. @@ -4376,8 +4376,8 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The items to refresh. + /// the source cache. + /// the items to refresh. /// is null. public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4393,7 +4393,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// is null. public static void Refresh(this ISourceCache source) where TObject : notnull @@ -4409,7 +4409,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// The item to remove. /// /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. @@ -4437,7 +4437,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// The key of the item to remove. /// is null. public static void Remove(this ISourceCache source, TKey key) @@ -4455,8 +4455,8 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The items to remove. + /// the source cache. + /// the items to remove. /// is null. public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4473,8 +4473,8 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The keys to remove. + /// the source cache. + /// the keys to remove. /// is null. public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull @@ -4486,7 +4486,7 @@ public static void Remove(this ISourceCache source } /// - /// The intermediate cache. + /// the intermediate cache. /// The key of the item to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) @@ -4499,8 +4499,8 @@ public static void Remove(this IIntermediateCache } /// - /// The intermediate cache. - /// The keys to remove. + /// the intermediate cache. + /// the keys to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) where TObject : notnull @@ -4517,7 +4517,7 @@ public static void Remove(this IIntermediateCache /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// A list changeset stream without key information. /// public static IObservable> RemoveKey(this IObservable> source) @@ -4539,7 +4539,7 @@ public static IObservable> RemoveKey(this IOb /// /// The type of the object. /// The type of the key. - /// The source cache. + /// the source cache. /// The key to remove. /// is null. public static void RemoveKey(this ISourceCache source, TKey key) @@ -4556,8 +4556,8 @@ public static void RemoveKey(this ISourceCache sou /// /// The type of the object. /// The type of the key. - /// The source cache. - /// The keys to remove. + /// the source cache. + /// the keys to remove. /// is null. public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull @@ -4569,9 +4569,9 @@ public static void RemoveKeys(this ISourceCache so } /// - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) @@ -4648,9 +4648,9 @@ public static IObservable> RightJoin - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. + /// the left changeset stream. + /// the right changeset stream. + /// A that maps each right item to the left key it should join on. /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) @@ -4733,7 +4733,7 @@ public static IObservable> RightJoinMany /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable that skips the first changeset and forwards all others. /// is null. /// @@ -4752,9 +4752,9 @@ public static IObservable> SkipInitial( /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The comparer. - /// Sort optimisation flags. Specify one or more sort optimisations. + /// A that sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). /// An observable which emits change sets. /// @@ -4778,9 +4778,9 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer observable. - /// The sort optimisations. + /// the source changeset stream. + /// the comparer observable. + /// the sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4799,10 +4799,10 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The comparer observable. - /// Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// the source changeset stream. + /// the comparer observable. + /// An that signal to instruct the algorithm to re-sort the entire data set. + /// the sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4821,10 +4821,10 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The comparer to sort on. - /// Signal to instruct the algorithm to re-sort the entire data set. - /// The sort optimisations. + /// An that signal to instruct the algorithm to re-sort the entire data set. + /// the sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4845,10 +4845,10 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// Expression that selects a comparable value from each item. + /// the source changeset stream. + /// A that expression that selects a comparable value from each item. /// The sort direction. Defaults to ascending. - /// Sort optimization flags. + /// A that sort optimization flags. /// The number of updates before the entire list is re-sorted (rather than inline sort). /// An observable that emits sorted changesets. public static IObservable> SortBy( @@ -4879,14 +4879,14 @@ public static IObservable> SortBy /// /// The type of the object. /// The type of the key. - /// The source observable change set. + /// the source observable change set. /// An observable that emits an empty changeset first, then all source changesets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); /// - /// The source observable sorted change set. + /// the source observable sorted change set. /// An observable that emits an empty sorted changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4894,7 +4894,7 @@ public static IObservable> StartWithEmpty source.StartWith(SortedChangeSet.Empty); /// - /// The source observable virtual change set. + /// the source observable virtual change set. /// An observable that emits an empty virtual changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4902,7 +4902,7 @@ public static IObservable> StartWithEmpty source.StartWith(VirtualChangeSet.Empty); /// - /// The source observable paged change set. + /// the source observable paged change set. /// An observable that emits an empty paged changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4913,7 +4913,7 @@ public static IObservable> StartWithEmptyThe type of the object. /// The type of the key. /// The grouping key type. - /// The source observable group change set. + /// the source observable group change set. /// An observable that emits an empty group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4925,7 +4925,7 @@ public static IObservable> StartWithEm /// The type of the object. /// The type of the key. /// The grouping key type. - /// The source observable immutable group change set. + /// the source observable immutable group change set. /// An observable that emits an empty immutable group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4935,13 +4935,13 @@ public static IObservable> St /// /// The type of the item. - /// The source read only collection observable. + /// the source read only collection observable. /// An observable that emits an empty collection first, then all source collections. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); /// - /// The source changeset stream. + /// the source changeset stream. /// The item to prepend. The key is extracted from . /// Overload for items that implement . Delegates to the explicit key overload. public static IObservable> StartWithItem(this IObservable> source, TObject item) @@ -4959,7 +4959,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The item to prepend. /// The key for the item. /// An observable that emits a single-item Add changeset first, then all source changesets. @@ -5017,7 +5017,7 @@ public static IObservable> SubscribeMany - /// The source changeset stream. + /// the source changeset stream. /// Factory that creates an for each item. Receives the item and its key. /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) @@ -5035,7 +5035,7 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// The source observable change set. + /// the source observable change set. /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull @@ -5088,7 +5088,7 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull @@ -5101,11 +5101,11 @@ public static IObservable> ToCollection /// The type of the object. /// The type of the key. - /// The source observable of individual items. - /// Selects the unique key for each item. - /// Optional: per-item expiration time. Return null for no expiration. + /// the source observable of individual items. + /// A that selects the unique key for each item. + /// A optional optional: per-item expiration time. Return null for no expiration. /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// Optional scheduler for expiration timing. + /// An optional optional scheduler for expiration timing. /// An observable changeset stream. /// or is null. public static IObservable> ToObservableChangeSet( @@ -5135,11 +5135,11 @@ public static IObservable> ToObservableChangeSet /// The type of the object. /// The type of the key. - /// The source observable of item batches. - /// Selects the unique key for each item. - /// Optional: per-item expiration time. Return null for no expiration. + /// the source observable of item batches. + /// A that selects the unique key for each item. + /// A optional optional: per-item expiration time. Return null for no expiration. /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// Optional scheduler for expiration timing. + /// An optional optional scheduler for expiration timing. /// An observable changeset stream. /// or is null. public static IObservable> ToObservableChangeSet( @@ -5205,7 +5205,7 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The key value. /// Indicates if an initial Optional None should be emitted if the value doesn't exist. /// Optional instance used to determine if an object value has changed. @@ -5238,8 +5238,8 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// The source changeset stream. - /// The sort function. + /// the source changeset stream. + /// the sort function. /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, Func sort, SortDirection sortOrder = SortDirection.Ascending) @@ -5252,7 +5252,7 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) @@ -5540,8 +5540,8 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source changeset observable. - /// A pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. + /// the source changeset observable. + /// a pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. /// An observable changeset of transformed items. /// /// @@ -5583,9 +5583,9 @@ public static IObservable> TransformImmutableThe type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source changeset of parent items. + /// the source changeset of parent items. /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. - /// Extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. + /// A that extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. /// An observable changeset of flattened child items. /// /// Change reason handling: @@ -5639,9 +5639,9 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source changeset of parent items. + /// the source changeset of parent items. /// An async function that expands a parent item (and its key) into an of children. - /// Extracts a unique key from each child item. + /// A that extracts a unique key from each child item. /// Optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. /// An observable changeset of flattened child items. @@ -5741,10 +5741,10 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source changeset of parent items. + /// the source changeset of parent items. /// An async function that expands a parent item (and its key) into an of children. - /// Extracts a unique key from each child item. - /// Called when throws. The faulting item is skipped and the stream continues. + /// A that extracts a unique key from each child item. + /// A that called when throws. The faulting item is skipped and the stream continues. /// Optional comparer to determine if two child items with the same key are equal. /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. /// An observable changeset of flattened child items. @@ -5929,10 +5929,10 @@ public static IObservable> TransformSafeThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source changeset observable. + /// the source changeset observable. /// A function that produces a from the current source item, the previous source item (if any), and the key. /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. + /// An optional an observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. /// An observable changeset of transformed items. /// /// @@ -6031,10 +6031,10 @@ public static IObservable> TransformSafeAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source changeset observable. + /// the source changeset observable. /// An async function that produces a . - /// Called when throws or faults. The item is skipped and the stream continues. - /// Optional observable to force re-transformation of matching items. + /// A that called when throws or faults. The item is skipped and the stream continues. + /// An optional optional observable to force re-transformation of matching items. /// An observable changeset of transformed items. /// Combines the async execution model of with the error-safe behavior of . /// , , or is null. @@ -6102,8 +6102,8 @@ public static IObservable> TransformSafeAsync /// The type of the source items. Must be a reference type. /// The type of the key. - /// The source changeset of flat items. - /// A function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. + /// the source changeset of flat items. + /// a function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. /// Optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. /// An observable changeset of items representing the tree. /// @@ -6180,8 +6180,8 @@ public static IObservable> TransformWithInlineUpd /// The type of the key. /// The source changeset observable. /// Called on Add (and optionally Refresh) to create a new . - /// Called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. - /// Called when or throws. The faulting item is skipped. + /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. + /// A that called when or throws. The faulting item is skipped. /// When true, Refresh changes call on the existing item. /// An observable changeset of transformed items. /// @@ -6217,7 +6217,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -6252,9 +6252,9 @@ static IEnumerable> ReplaceMoves(IChangeSet /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each per-item observable's latest value. + /// the source changeset stream. + /// A that factory that produces a condition observable for each item. + /// A that predicate applied to each per-item observable's latest value. /// An observable of bool that emits whenever the all-items condition changes. /// , , or is null. /// @@ -6288,9 +6288,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// The source changeset stream. - /// Selector which returns the target observable. - /// The equality condition. + /// the source changeset stream. + /// A that selector which returns the target observable. + /// the equality condition. /// An observable which boolean values indicating if true. /// source. public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -6305,9 +6305,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each item and its per-item observable's latest value. + /// the source changeset stream. + /// A that factory that produces a condition observable for each item. + /// A that predicate applied to each item and its per-item observable's latest value. /// An observable of bool that emits whenever the any-item condition changes. /// , , or is null. /// @@ -6329,9 +6329,9 @@ public static IObservable TrueForAny(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// The source changeset stream. - /// Factory that produces a condition observable for each item. - /// Predicate applied to each per-item observable's latest value (without the item). + /// the source changeset stream. + /// A that factory that produces a condition observable for each item. + /// A that predicate applied to each per-item observable's latest value (without the item). /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull @@ -6351,7 +6351,7 @@ public static IObservable TrueForAny(this IObservab /// /// The type of the object. /// The type of the key. - /// The source sorted changeset stream. + /// the source sorted changeset stream. /// An observable that emits the sorted changesets after updating item indices. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware @@ -6363,7 +6363,7 @@ public static IObservable> UpdateIndex /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The key to observe. /// An observable of for the specified key only. /// @@ -6423,7 +6423,7 @@ public static IObservable WatchValue(this IObservableCac } /// - /// The source changeset stream. + /// the source changeset stream. /// The key to observe. /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) @@ -6481,7 +6481,7 @@ public static IObservable WatchValue(this IObservableThe type of the key. /// The type of the monitored property. /// The source changeset stream. - /// Expression selecting the property to monitor. + /// A that expression selecting the property to monitor. /// When true (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of containing both the item and its property value. /// @@ -6555,7 +6555,7 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The reasons. /// An observable which emits a change set with items matching the reasons. /// reasons. @@ -6585,7 +6585,7 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// the source changeset stream. /// The reasons. /// An observable which emits a change set with items not matching the reasons. /// reasons. @@ -6687,7 +6687,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull @@ -6704,7 +6704,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull From 65dd5aeb2651091e99a4aa2a2677473be7b9f5c8 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:30:30 -0700 Subject: [PATCH 13/23] docs: add type links to cache operator param descriptions Surgical param-by-param replacement preserving all existing event tables, seealso, inheritdoc, and worth-noting sections. 528/618 params linked (85%). Remaining 90 are exempt (bool, int, enum, domain-type params). --- src/DynamicData/Cache/ObservableCacheEx.cs | 368 ++++++++++----------- 1 file changed, 184 insertions(+), 184 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index b92abe8ea..4be3fdc88 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -33,8 +33,8 @@ public static partial class ObservableCacheEx /// /// The type of items in the cache. /// The type of the key. - /// The source changeset stream. - /// The adaptor whose Adapt method is called for each changeset. + /// The source of . + /// the adaptor whose Adapt method is called for each changeset. /// An observable that emits the same changesets as , after the adaptor has processed each one. /// /// @@ -66,7 +66,7 @@ public static IObservable> Adapt(this I /// /// the source sorted changeset stream. - /// The sorted adaptor whose Adapt method is called for each sorted changeset. + /// the sorted adaptor whose Adapt method is called for each sorted changeset. /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) where TObject : notnull @@ -113,7 +113,7 @@ public static void AddOrUpdate(this ISourceCache s /// /// the source cache. /// The item to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// the equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull @@ -140,7 +140,7 @@ public static void AddOrUpdate(this ISourceCache s /// /// the source cache. /// the items to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// the equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull @@ -173,7 +173,7 @@ public static void AddOrUpdate(this IIntermediateCacheThe type of the object. /// The type of the key. /// the source changeset stream. - /// The others. + /// the others. /// An observable which emits change sets. /// source or others. public static IObservable> And(this IObservable> source, params IObservable>[] others) @@ -192,7 +192,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. /// /// source @@ -214,7 +214,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -323,7 +323,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of items in the cache. /// The type of the key. - /// The source changeset stream. + /// The source of . /// /// /// Invoked once per subscription, providing an that signals when all @@ -472,8 +472,8 @@ public static IObservable> AutoRefreshOnObservable /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The time window for batching. + /// The source of . + /// the time window for batching. /// The scheduler for timing. Defaults to . /// An observable that emits merged changesets, one per time window. /// @@ -528,11 +528,11 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// When true, buffering begins. When false, the buffer is flushed. + /// The source of . + /// An that when true, buffering begins. When false, the buffer is flushed. /// If true, starts in a paused (buffering) state. - /// Maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. - /// The scheduler for timeout timing. + /// A that maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. + /// the scheduler for timeout timing. /// An observable that emits changesets, buffered or passthrough depending on pause state. /// /// @@ -811,7 +811,7 @@ public static IObservable> Bind(this IO /// The resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// Specify an adaptor to change the algorithm to update the target collection. + /// An that specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, ISortedObservableCollectionAdaptor? adaptor = null) @@ -1188,7 +1188,7 @@ public static IObservable> DeferUntilLoaded /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// A stream that forwards all changesets from unchanged. /// /// @@ -1397,7 +1397,7 @@ public static IObservable> EnsureUniqueKeysThe type of the object. /// The type of the key. /// the source changeset stream. - /// The others. + /// the others. /// An observable which emits change sets. /// /// source @@ -1424,7 +1424,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The sources. + /// the sources. /// An observable which emits change sets. /// /// source @@ -1446,7 +1446,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1664,9 +1664,9 @@ public static IObservable> Filter( /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source changeset stream. - /// A stream of state values to be passed to . - /// A predicate that receives the current state and an item, returning true to include or false to exclude. + /// The source of . + /// a stream of state values to be passed to . + /// a predicate that receives the current state and an item, returning true to include or false to exclude. /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets. /// An observable changeset containing only items satisfying for the latest state. /// , , or is null. @@ -1733,7 +1733,7 @@ public static IObservable> Filter( /// The type of collection items to be filtered. /// The type of the key values of each collection item. /// The source stream of collection items to be filtered. - /// The filtering predicate to be applied to each item. + /// the filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. /// @@ -1780,10 +1780,10 @@ public static IObservable> FilterImmutable /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// A factory that creates an for each item and its key. When the observable emits true, the item is included; when false, it is excluded. - /// Optional time window to buffer inclusion changes from per-item observables before re-evaluating. - /// Optional scheduler used for buffering. + /// A that optional time window to buffer inclusion changes from per-item observables before re-evaluating. + /// An that optional scheduler used for buffering. /// An observable changeset containing only items whose per-item observable most recently emitted true. /// /// @@ -1932,7 +1932,7 @@ public static IObservable> ForEachChange the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) where TLeft : notnull @@ -1959,10 +1959,10 @@ public static IObservable> FullJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . /// /// @@ -2011,7 +2011,7 @@ public static IObservable> FullJoin the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull @@ -2039,10 +2039,10 @@ public static IObservable> FullJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . /// /// @@ -2122,8 +2122,8 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Extracts the group key from each item. + /// The source of . + /// A that extracts the group key from each item. /// An observable that emits group changesets. Each group exposes a sub-cache of its members. /// /// @@ -2184,9 +2184,9 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// An observable that emits group selector functions. Each emission triggers a full re-grouping of all items. - /// Optional signal to force re-evaluation of all items against the current selector. + /// The source of . + /// an observable that emits group selector functions. Each emission triggers a full re-grouping of all items. + /// An that optional signal to force re-evaluation of all items against the current selector. /// An observable that emits group changesets. /// /// @@ -2239,8 +2239,8 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Factory that creates a group key observable for each item and its key. + /// The source of . + /// A that factory that creates a group key observable for each item and its key. /// An observable that emits group changesets. Each group is a live sub-cache of its members. /// /// @@ -2362,9 +2362,9 @@ public static IObservable> Gr /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source changeset stream. - /// Extracts the group key from each item. - /// Optional signal to force re-evaluation of all items against the group selector. + /// The source of . + /// A that extracts the group key from each item. + /// An that optional signal to force re-evaluation of all items against the group selector. /// An observable that emits immutable group changesets. /// /// @@ -2488,10 +2488,10 @@ public static IObservable> IncludeUpdateWhenThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. /// /// @@ -2541,7 +2541,7 @@ public static IObservable> IncludeUpdateWhen the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull @@ -2568,10 +2568,10 @@ public static IObservable> InnerJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . /// /// @@ -2643,7 +2643,7 @@ public static IObservable> InvokeEvaluate the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the left value and the optional right into a destination object. The key is not provided in this overload. + /// A that combines the left value and the optional right into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull @@ -2670,10 +2670,10 @@ public static IObservable> LeftJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . /// /// @@ -2722,7 +2722,7 @@ public static IObservable> LeftJoin the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the left value and the right group into a destination object. The key is not provided in this overload. + /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) where TLeft : notnull @@ -2749,10 +2749,10 @@ public static IObservable> LeftJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . /// /// @@ -2888,7 +2888,7 @@ public static IObservable>> LimitSizeTo< /// The type of the key identifying source cache items. /// The type of values emitted by child observables. /// The source cache changeset stream. - /// Factory function that produces a child observable for each source item. + /// A that factory function that produces a child observable for each source item. /// An observable that emits values from all active child observables, interleaved by arrival order. /// /// @@ -2942,7 +2942,7 @@ public static IObservable MergeMany(t /// /// The type of items in the changesets. /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. + /// An that emits changeset streams. Each inner stream is subscribed as it appears. /// A unified changeset stream containing changes from all active source streams. /// /// @@ -2997,8 +2997,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that emits changeset streams. Each inner stream is subscribed as it appears. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// A unified changeset stream containing changes from all active source streams. /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IComparer comparer) @@ -3018,8 +3018,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that emits changeset streams. Each inner stream is subscribed as it appears. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// A unified changeset stream containing changes from all active source streams. /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer) @@ -3038,9 +3038,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// An observable that emits changeset streams. Each inner stream is subscribed as it appears. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that emits changeset streams. Each inner stream is subscribed as it appears. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// A unified changeset stream containing changes from all active source streams. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer, IComparer comparer) @@ -3083,7 +3083,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// the first changeset stream. /// the second changeset stream to merge with . - /// Comparer to determine which value wins when both sources provide the same key. + /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3106,7 +3106,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// the first changeset stream. /// the second changeset stream to merge with . - /// Equality comparer to detect duplicate values for the same key. + /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3129,8 +3129,8 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// the first changeset stream. /// the second changeset stream to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Comparer to determine which value wins when both sources provide the same key. + /// An that equality comparer to detect duplicate values for the same key. + /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when both streams complete. If false, the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3154,7 +3154,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// the primary changeset stream. - /// Additional changeset streams to merge with . + /// An that additional changeset streams to merge with . /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3175,8 +3175,8 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// the primary changeset stream. - /// Additional changeset streams to merge with . - /// Comparer to determine which value wins when multiple sources provide the same key. + /// An that additional changeset streams to merge with . + /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3198,8 +3198,8 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// the primary changeset stream. - /// Additional changeset streams to merge with . - /// Equality comparer to detect duplicate values for the same key. + /// An that additional changeset streams to merge with . + /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3221,9 +3221,9 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// the primary changeset stream. - /// Additional changeset streams to merge with . - /// Equality comparer to detect duplicate values for the same key. - /// Comparer to determine which value wins when multiple sources provide the same key. + /// An that additional changeset streams to merge with . + /// An that equality comparer to detect duplicate values for the same key. + /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all streams complete. If false, the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3279,7 +3279,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// The collection of changeset streams to merge. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3302,7 +3302,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// The collection of changeset streams to merge. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3324,8 +3324,8 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// The collection of changeset streams to merge. - /// Equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// Comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3351,8 +3351,8 @@ public static IObservable> MergeChangeSetsThe type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) @@ -3375,8 +3375,8 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) @@ -3401,9 +3401,9 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// Optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// An that optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -3427,10 +3427,10 @@ public static IObservable> MergeManyCh /// The type of the key identifying parent items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source cache changeset stream whose items each produce a child changeset stream. - /// Factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. - /// Optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. - /// Optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. + /// The source of whose items each produce a child changeset stream. + /// A that factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. + /// An that optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. + /// An that optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. /// A merged changeset stream containing all child items from all active parent subscriptions. /// /// @@ -3501,9 +3501,9 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) @@ -3528,9 +3528,9 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) @@ -3548,10 +3548,10 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) @@ -3575,10 +3575,10 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. + /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) @@ -3597,10 +3597,10 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3624,10 +3624,10 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3645,11 +3645,11 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. + /// A that factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value. - /// Optional fallback comparer for destination key conflicts when source items compare equal. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3675,11 +3675,11 @@ public static IObservable> MergeManyCh /// The type of items in the child changeset streams. /// The type of the key identifying child items. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child cache changeset stream. - /// Comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. - /// Optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// Optional fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// An that optional fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. /// /// @@ -3714,8 +3714,8 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. /// the source cache changeset stream. - /// Factory function that receives a source item and its key, and returns a child list changeset stream. - /// Optional equality comparer to detect duplicate items in the merged list output. + /// A that factory function that receives a source item and its key, and returns a child list changeset stream. + /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull @@ -3736,8 +3736,8 @@ public static IObservable> MergeManyChangeSetsThe type of the key identifying source cache items. /// The type of items in the child list changeset streams. /// the source cache changeset stream. - /// Factory function that receives a source item and returns a child list changeset stream. - /// Optional equality comparer to detect duplicate items in the merged list output. + /// A that factory function that receives a source item and returns a child list changeset stream. + /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull @@ -3850,8 +3850,8 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each added item. Receives the new item and its key. + /// The source of . + /// the callback invoked for each added item. Receives the new item and its key. /// A stream that forwards all changesets from unchanged. /// /// @@ -3896,7 +3896,7 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// the callback invoked for each refreshed item. Receives the item and its key. /// A stream that forwards all changesets from unchanged. /// @@ -3941,8 +3941,8 @@ public static IObservable> OnItemRefreshed /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each removed item. Receives the removed item and its key. + /// The source of . + /// the callback invoked for each removed item. Receives the removed item and its key. /// /// When true (the default), the callback is also invoked for every item still in the cache /// when the subscription is disposed. When false, only inline Remove changes trigger the callback. @@ -4005,8 +4005,8 @@ public static IObservable> OnItemRemoved /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The callback invoked for each updated item. Receives the current value, previous value, and key. + /// The source of . + /// the callback invoked for each updated item. Receives the current value, previous value, and key. /// A stream that forwards all changesets from unchanged. /// /// @@ -4051,7 +4051,7 @@ public static IObservable> OnItemUpdatedThe type of the object. /// The type of the key. /// The first source changeset stream. - /// Additional changeset streams to combine with. + /// An that additional changeset streams to combine with. /// A changeset stream containing items present in any of the sources. /// /// @@ -4088,7 +4088,7 @@ public static IObservable> Or(this IObs } /// - /// A fixed collection of changeset streams to combine. + /// a fixed collection of changeset streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Or(this ICollection>> sources) where TObject : notnull @@ -4105,7 +4105,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -4196,7 +4196,7 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// the destination cache to populate. /// An that, when disposed, unsubscribes from the source. /// @@ -4572,7 +4572,7 @@ public static void RemoveKeys(this ISourceCache so /// the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the optional left and right values into a destination object. The key is not provided in this overload. + /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) where TLeft : notnull @@ -4599,10 +4599,10 @@ public static IObservable> RightJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). /// An observable changeset keyed by . /// /// @@ -4651,7 +4651,7 @@ public static IObservable> RightJoin the left changeset stream. /// the right changeset stream. /// A that maps each right item to the left key it should join on. - /// Combines the optional left value and the right group into a destination object. The key is not provided in this overload. + /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) where TLeft : notnull @@ -4679,10 +4679,10 @@ public static IObservable> RightJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left changeset stream. - /// The right changeset stream. - /// Maps each right item to the left key it should join on. - /// Combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). + /// of the left changeset stream. + /// of the right changeset stream. + /// A that maps each right item to the left key it should join on. + /// A that combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . /// /// @@ -4753,7 +4753,7 @@ public static IObservable> SkipInitial( /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The comparer. + /// the comparer. /// A that sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). /// An observable which emits change sets. @@ -4822,7 +4822,7 @@ public static IObservable> Sort(t /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The comparer to sort on. + /// the comparer to sort on. /// An that signal to instruct the algorithm to re-sort the entire data set. /// the sort optimisations. /// The reset threshold. @@ -4980,7 +4980,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// Factory that creates an for each item. Called on Add and Update (for the new value). /// A stream that forwards all changesets from unchanged. /// @@ -5059,7 +5059,7 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// An observable that emits inner changeset streams. + /// an observable that emits inner changeset streams. /// A changeset stream reflecting the items from the most recently emitted inner source. /// /// @@ -5168,9 +5168,9 @@ public static IObservable> ToObservableChangeSet /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// The key to watch. - /// Optional comparer to suppress duplicate emissions. Uses default equality if null. + /// An that optional comparer to suppress duplicate emissions. Uses default equality if null. /// An observable of that reflects the presence or absence of the specified key. /// /// @@ -5253,7 +5253,7 @@ public static IObservable> ToSortedCollectionThe type of the object. /// The type of the key. /// the source changeset stream. - /// The sort comparer. + /// the sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) where TObject : notnull @@ -5336,8 +5336,8 @@ public static IObservable> TransformThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source changeset observable. - /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// The source of . + /// a function that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. /// An observable changeset of transformed items. /// @@ -5453,8 +5453,8 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source changeset observable. - /// An async function that produces a from the current source item, the previous source item (if any), and the key. + /// The source of . + /// an async function that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. /// An observable changeset of transformed items. /// @@ -5642,8 +5642,8 @@ public static IObservable> TransformMa /// the source changeset of parent items. /// An async function that expands a parent item (and its key) into an of children. /// A that extracts a unique key from each child item. - /// Optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. - /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. + /// An that optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. + /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. /// An observable changeset of flattened child items. /// /// @@ -5745,8 +5745,8 @@ public static IObservable> TransformMa /// An async function that expands a parent item (and its key) into an of children. /// A that extracts a unique key from each child item. /// A that called when throws. The faulting item is skipped and the stream continues. - /// Optional comparer to determine if two child items with the same key are equal. - /// Optional comparer to resolve key collisions when the same destination key is produced by multiple parents. + /// An that optional comparer to determine if two child items with the same key are equal. + /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. /// An observable changeset of flattened child items. /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. /// , , or is null. @@ -5835,7 +5835,7 @@ public static IObservable> TransformMa /// The type of the source items. /// The type of the key. /// The type of the transformed items. - /// The source changeset observable. + /// The source of . /// A function that, given a source item and its key, returns an whose emissions become the transformed values. /// An observable changeset where each key's value is the latest emission from its per-item observable. /// @@ -5930,7 +5930,7 @@ public static IObservable> TransformSafeThe type of the source items. /// The type of the key. /// the source changeset observable. - /// A function that produces a from the current source item, the previous source item (if any), and the key. + /// a function that produces a from the current source item, the previous source item (if any), and the key. /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. /// An optional an observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. /// An observable changeset of transformed items. @@ -6032,7 +6032,7 @@ public static IObservable> TransformSafeAsyncThe type of the source items. /// The type of the key. /// the source changeset observable. - /// An async function that produces a . + /// an async function that produces a . /// A that called when throws or faults. The item is skipped and the stream continues. /// An optional optional observable to force re-transformation of matching items. /// An observable changeset of transformed items. @@ -6104,7 +6104,7 @@ public static IObservable> TransformSafeAsyncThe type of the key. /// the source changeset of flat items. /// a function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. - /// Optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. + /// An that optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. /// An observable changeset of items representing the tree. /// /// Change reason handling: @@ -6178,8 +6178,8 @@ public static IObservable> TransformWithInlineUpd /// The type of the transformed items. Must be a reference type since items are mutated in place. /// The type of the source items. /// The type of the key. - /// The source changeset observable. - /// Called on Add (and optionally Refresh) to create a new . + /// The source of . + /// A that called on Add (and optionally Refresh) to create a new . /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. /// A that called when or throws. The faulting item is skipped. /// When true, Refresh changes call on the existing item. @@ -6391,7 +6391,7 @@ public static IObservable> Watch(this IObse /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source of . /// The key to observe. /// An observable of the item's value whenever it changes for the specified key. /// @@ -6441,7 +6441,7 @@ public static IObservable WatchValue(this IObservable /// The type of the object (must implement ). /// The type of the key. - /// The source changeset stream. + /// The source of . /// Specific property names to monitor. If empty, all property changes trigger emissions. /// An observable that emits the item itself each time a monitored property changes. /// @@ -6480,7 +6480,7 @@ public static IObservable WatchValue(this IObservableThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source changeset stream. + /// The source of . /// A that expression selecting the property to monitor. /// When true (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of containing both the item and its property value. @@ -6517,8 +6517,8 @@ public static IObservable> WhenPropertyChangedThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source changeset stream. - /// Expression selecting the property to monitor. + /// The source of . + /// A that expression selecting the property to monitor. /// When true (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of property values. The owning item is not included; use if you need it. /// @@ -6616,7 +6616,7 @@ public static IObservable> WhereReasonsAreNotThe type of the object. /// The type of the key. /// The first source changeset stream. - /// Additional changeset streams to combine with. + /// An that additional changeset streams to combine with. /// A changeset stream containing items present in exactly one source. /// /// @@ -6653,7 +6653,7 @@ public static IObservable> Xor(this IOb } /// - /// A fixed collection of changeset streams to combine. + /// a fixed collection of changeset streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Xor(this ICollection>> sources) where TObject : notnull @@ -6670,7 +6670,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// The source collection of changeset streams. + /// the source collection of changeset streams. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull From 62e005dd393c95f329acc86ded50aa18c99378c1 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:34:04 -0700 Subject: [PATCH 14/23] docs: link remaining non-primitive param types Fix multiline params (pollingInterval, resultGroupSource) and add typeparamref links for domain-type params (key, item). 570/618 linked (92%). Remaining 48 are bool/int primitives. --- src/DynamicData/Cache/ObservableCacheEx.cs | 87 +++++++++++----------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 4be3fdc88..164af4df6 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -85,7 +85,7 @@ public static IObservable> Adapt(this I /// The type of the object. /// The type of the key. /// the source cache. - /// The item to add or update. + /// The item to add or update. /// /// Convenience method that wraps a single-item mutation inside . /// @@ -112,7 +112,7 @@ public static void AddOrUpdate(this ISourceCache s /// /// the source cache. - /// The item to add or update. + /// The item to add or update. /// the equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) @@ -153,8 +153,8 @@ public static void AddOrUpdate(this ISourceCache s /// /// the source intermediate cache. - /// The item to add or update. - /// The key to associate with the item. + /// The item to add or update. + /// The key to associate with the item. /// This overload operates on , which requires an explicit key parameter. public static void AddOrUpdate(this IIntermediateCache source, TObject item, TKey key) where TObject : notnull @@ -608,7 +608,7 @@ public static IObservable> Bind(this IO /// The type of the key. /// the source changeset stream. /// the destination. - /// The binding options. + /// A that The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -657,8 +657,8 @@ public static IObservable> Bind(this IO /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The resulting read only observable collection. - /// The binding options. + /// the resulting read only observable collection. + /// A that The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -678,7 +678,7 @@ public static IObservable> Bind(this IO /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The resulting read only observable collection. + /// the resulting read only observable collection. /// The number of changes before a reset notification is triggered. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. /// An optional specify an adaptor to change the algorithm to update the target collection. @@ -734,7 +734,7 @@ public static IObservable> Bind(t /// The type of the key. /// the source changeset stream. /// the destination. - /// The binding options. + /// A that The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -755,7 +755,7 @@ public static IObservable> Bind(t /// The type of the key. /// the source changeset stream. /// the destination. - /// The updater. + /// the updater. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, ISortedObservableCollectionAdaptor updater) @@ -785,8 +785,8 @@ public static IObservable> Bind(t /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The resulting read only observable collection. - /// The binding options. + /// the resulting read only observable collection. + /// A that The binding options. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -808,7 +808,7 @@ public static IObservable> Bind(this IO /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The resulting read only observable collection. + /// the resulting read only observable collection. /// The number of changes before a reset event is called on the observable collection. /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. /// An that specify an adaptor to change the algorithm to update the target collection. @@ -842,7 +842,7 @@ public static IObservable> Bind(this IO /// The object type. /// The key type. /// the source changeset stream. - /// The target binding list. + /// the target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -866,7 +866,7 @@ public static IObservable> Bind(this IO /// The object type. /// The key type. /// the source changeset stream. - /// The target binding list. + /// the target binding list. /// The reset threshold. /// An observable which will emit change sets. /// @@ -1541,8 +1541,7 @@ public static IObservable> ExpireAfter( /// /// the source changeset stream. /// A optional a function returning the expiration timeout for each item, or null for no expiration. - /// If specified, items are expired on a polling interval rather than per-item timers. - /// This is less accurate but more efficient when many items share similar expiration times. + /// An optional polling interval. If specified, items are expired on a polling interval rather than per-item timers. Less accurate but more efficient when many items share similar expiration times. /// /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next /// poll after their timeout elapses, which trades accuracy for reduced timer overhead. @@ -1732,7 +1731,7 @@ public static IObservable> Filter( /// /// The type of collection items to be filtered. /// The type of the key values of each collection item. - /// The source stream of collection items to be filtered. + /// the source stream of collection items to be filtered. /// the filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. @@ -1882,7 +1881,7 @@ public static IObservable> Flatten(this IOb /// /// The type of the object. /// The type of the key. - /// The source observable of buffered changeset lists. + /// the source observable of buffered changeset lists. /// An observable changeset combining all changes from each buffer into a single emission. /// is null. public static IObservable> FlattenBufferResult(this IObservable>> source) @@ -2096,9 +2095,7 @@ public static IObservable> FullJoinManyThe type of the group key. /// the source changeset stream. /// the group selector factory. - /// - /// A distinct stream used to determine the result. - /// + /// An of used to determine which groups appear in the result. /// /// Useful for parent-child collection when the parent and child are soured from different streams. /// @@ -2887,7 +2884,7 @@ public static IObservable>> LimitSizeTo< /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source cache changeset stream. + /// the source cache changeset stream. /// A that factory function that produces a child observable for each source item. /// An observable that emits values from all active child observables, interleaved by arrival order. /// @@ -3246,7 +3243,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The collection of changeset streams to merge. + /// the collection of changeset streams to merge. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3278,7 +3275,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The collection of changeset streams to merge. + /// the collection of changeset streams to merge. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. @@ -3301,7 +3298,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The collection of changeset streams to merge. + /// the collection of changeset streams to merge. /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An optional optional scheduler used when subscribing to the source streams. /// If true (default), the output completes when all source streams have completed. If false, the output never completes. @@ -3323,7 +3320,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The collection of changeset streams to merge. + /// the collection of changeset streams to merge. /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. @@ -4050,7 +4047,7 @@ public static IObservable> OnItemUpdated /// The type of the object. /// The type of the key. - /// The first source changeset stream. + /// the first source changeset stream. /// An that additional changeset streams to combine with. /// A changeset stream containing items present in any of the sources. /// @@ -4350,7 +4347,7 @@ public static IObservable> RefCount(thi /// The type of the object. /// The type of the key. /// the source cache. - /// The item to refresh. + /// The item to refresh. /// /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. /// @@ -4410,7 +4407,7 @@ public static void Refresh(this ISourceCache sourc /// The type of the object. /// The type of the key. /// the source cache. - /// The item to remove. + /// The item to remove. /// /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. /// @@ -4438,7 +4435,7 @@ public static void Remove(this ISourceCache source /// The type of the object. /// The type of the key. /// the source cache. - /// The key of the item to remove. + /// The key of the item to remove. /// is null. public static void Remove(this ISourceCache source, TKey key) where TObject : notnull @@ -4487,7 +4484,7 @@ public static void Remove(this ISourceCache source /// /// the intermediate cache. - /// The key of the item to remove. + /// The key of the item to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) where TObject : notnull @@ -4540,7 +4537,7 @@ public static IObservable> RemoveKey(this IOb /// The type of the object. /// The type of the key. /// the source cache. - /// The key to remove. + /// The key to remove. /// is null. public static void RemoveKey(this ISourceCache source, TKey key) where TObject : notnull @@ -4847,7 +4844,7 @@ public static IObservable> Sort(t /// The type of the key. /// the source changeset stream. /// A that expression that selects a comparable value from each item. - /// The sort direction. Defaults to ascending. + /// the sort direction. Defaults to ascending. /// A that sort optimization flags. /// The number of updates before the entire list is re-sorted (rather than inline sort). /// An observable that emits sorted changesets. @@ -4960,8 +4957,8 @@ public static IObservable> StartWithItemThe type of the object. /// The type of the key. /// the source changeset stream. - /// The item to prepend. - /// The key for the item. + /// The item to prepend. + /// The key for the item. /// An observable that emits a single-item Add changeset first, then all source changesets. public static IObservable> StartWithItem(this IObservable> source, TObject item, TKey key) where TObject : notnull @@ -5169,7 +5166,7 @@ public static IObservable> ToObservableChangeSetThe type of the object. /// The type of the key. /// The source of . - /// The key to watch. + /// The key to watch. /// An that optional comparer to suppress duplicate emissions. Uses default equality if null. /// An observable of that reflects the presence or absence of the specified key. /// @@ -5206,7 +5203,7 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// the source changeset stream. - /// The key value. + /// The key value. /// Indicates if an initial Optional None should be emitted if the value doesn't exist. /// Optional instance used to determine if an object value has changed. /// An observable optional. @@ -5240,7 +5237,7 @@ public static IObservable> ToObservableOptional /// The sort key. /// the source changeset stream. /// the sort function. - /// The sort order. Defaults to ascending. + /// the sort order. Defaults to ascending. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, Func sort, SortDirection sortOrder = SortDirection.Ascending) where TObject : notnull @@ -6364,7 +6361,7 @@ public static IObservable> UpdateIndexThe type of the object. /// The type of the key. /// the source changeset stream. - /// The key to observe. + /// The key to observe. /// An observable of for the specified key only. /// /// @@ -6392,7 +6389,7 @@ public static IObservable> Watch(this IObse /// The type of the object. /// The type of the key. /// The source of . - /// The key to observe. + /// The key to observe. /// An observable of the item's value whenever it changes for the specified key. /// /// @@ -6424,7 +6421,7 @@ public static IObservable WatchValue(this IObservableCac /// /// the source changeset stream. - /// The key to observe. + /// The key to observe. /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) where TObject : notnull @@ -6556,7 +6553,7 @@ public static IObservable> WhenPropertyChangedThe type of the object. /// The type of the key. /// the source changeset stream. - /// The reasons. + /// the reasons. /// An observable which emits a change set with items matching the reasons. /// reasons. /// Must select at least on reason. @@ -6586,7 +6583,7 @@ public static IObservable> WhereReasonsAreThe type of the object. /// The type of the key. /// the source changeset stream. - /// The reasons. + /// the reasons. /// An observable which emits a change set with items not matching the reasons. /// reasons. /// Must select at least on reason. @@ -6615,7 +6612,7 @@ public static IObservable> WhereReasonsAreNot /// The type of the object. /// The type of the key. - /// The first source changeset stream. + /// the first source changeset stream. /// An that additional changeset streams to combine with. /// A changeset stream containing items present in exactly one source. /// From 91c32fab223a104727a2f1254522a0fbb1282502 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:44:08 -0700 Subject: [PATCH 15/23] docs: use see langword for C# keywords (true, false, null) Replace true, false, null with , , for proper keyword rendering in generated HTML documentation. Also update documentation skill with langword guidance. --- src/DynamicData/Cache/ObservableCacheEx.cs | 292 ++++++++++----------- 1 file changed, 146 insertions(+), 146 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 164af4df6..181f03687 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -51,7 +51,7 @@ public static partial class ObservableCacheEx /// OnCompletedForwarded to the downstream observer. /// /// - /// or is null. + /// or is . /// /// public static IObservable> Adapt(this IObservable> source, IChangeSetAdaptor adaptor) @@ -98,7 +98,7 @@ public static IObservable> Adapt(this I /// OnCompletedNot applicable (synchronous mutation). /// /// - /// is null. + /// is . /// /// public static void AddOrUpdate(this ISourceCache source, TObject item) @@ -266,7 +266,7 @@ public static IObservable> And(this IOb /// The type of the key. /// the source cache to wrap. /// A read-only . - /// is null. + /// is . /// public static IObservableCache AsObservableCache(this IObservableCache source) where TObject : notnull @@ -284,16 +284,16 @@ public static IObservableCache AsObservableCache(t /// The type of the object. /// The type of the key. /// the source changeset stream. - /// If true (default), all cache operations are synchronized. Set to false when the caller guarantees single-threaded access. + /// If (default), all cache operations are synchronized. Set to when the caller guarantees single-threaded access. /// A read-only observable cache that reflects the current state of the pipeline. /// /// /// Disposing the returned cache unsubscribes from the source stream. The cache's Connect() /// method provides a changeset stream of its own, which re-emits the current state on each new subscriber. /// - /// When is false, a is used internally. + /// When is , a is used internally. /// - /// is null. + /// is . /// /// public static IObservableCache AsObservableCache(this IObservable> source, bool applyLocking = true) @@ -353,7 +353,7 @@ public static IObservableCache AsObservableCache(t /// are dispatched via the signal. /// /// - /// or is null. + /// or is . /// public static IObservable> AsyncDisposeMany( this IObservable> source, @@ -492,7 +492,7 @@ public static IObservable> AutoRefreshOnObservable /// Worth noting: The merged changeset may contain contradictory changes (e.g., Add then Remove for the same key). Downstream operators handle this correctly, but raw inspection of the changeset may be surprising. /// - /// is null. + /// is . /// /// public static IObservable> Batch(this IObservable> source, TimeSpan timeSpan, IScheduler? scheduler = null) @@ -517,7 +517,7 @@ public static IObservable> BatchIf(this where TKey : notnull => new BatchIf(source, pauseIfTrueSelector, null, initialPauseState, scheduler: scheduler).Run(); /// - /// This overload omits initialPauseState (defaults to false) but accepts a timeout. + /// This overload omits initialPauseState (defaults to ) but accepts a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, TimeSpan? timeOut = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => BatchIf(source, pauseIfTrueSelector, false, timeOut, scheduler); @@ -529,8 +529,8 @@ public static IObservable> BatchIf(this /// The type of the object. /// The type of the key. /// The source of . - /// An that when true, buffering begins. When false, the buffer is flushed. - /// If true, starts in a paused (buffering) state. + /// An that when , buffering begins. When , the buffer is flushed. + /// If , starts in a paused (buffering) state. /// A that maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. /// the scheduler for timeout timing. /// An observable that emits changesets, buffered or passthrough depending on pause state. @@ -550,7 +550,7 @@ public static IObservable> BatchIf(this /// /// Worth noting: If the source completes while paused, buffered data IS flushed before OnCompleted. However, if the source errors while paused, buffered data is lost. /// - /// or is null. + /// or is . /// /// public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, TimeSpan? timeOut = null, IScheduler? scheduler = null) @@ -565,8 +565,8 @@ public static IObservable> BatchIf(this /// /// the source changeset stream. - /// An that when true, buffering begins. When false, the buffer is flushed. - /// If true, starts in a paused (buffering) state. + /// An that when , buffering begins. When , the buffer is flushed. + /// If , starts in a paused (buffering) state. /// An optional an observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. /// An optional the scheduler. /// This overload accepts an explicit timer observable instead of a timeout. @@ -1024,7 +1024,7 @@ public static IObservable> ChangeKeyOnCompletedNot applicable (synchronous mutation method). /// /// - /// is null. + /// is . public static void Clear(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -1207,7 +1207,7 @@ public static IObservable> DeferUntilLoaded, use instead. /// /// - /// is null. + /// is . /// /// public static IObservable> DisposeMany(this IObservable> source) @@ -1271,7 +1271,7 @@ public static void EditDiff(this ISourceCache sour /// The type of the key. /// the source cache to diff against. /// the complete snapshot of desired items. - /// a function that returns true when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// a function that returns when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. /// /// /// EventBehavior @@ -1283,7 +1283,7 @@ public static void EditDiff(this ISourceCache sour /// OnCompletedNot applicable (synchronous mutation method). /// /// - /// , , or is null. + /// , , or is . public static void EditDiff(this ISourceCache source, IEnumerable allItems, Func areItemsEqual) where TObject : notnull where TKey : notnull @@ -1305,7 +1305,7 @@ public static void EditDiff(this ISourceCache sour /// The type of the key. /// the source observable of item snapshots. /// a function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if null. + /// Optional for comparing items. Uses default equality if . /// An observable changeset representing the incremental differences between successive snapshots. /// /// @@ -1318,7 +1318,7 @@ public static void EditDiff(this ISourceCache sour /// OnCompletedForwarded to the downstream observer. /// /// - /// or is null. + /// or is . /// public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull @@ -1338,7 +1338,7 @@ public static IObservable> EditDiff(thi /// The type of the key. /// the source observable of optional values. /// a function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if null. + /// Optional for comparing items. Uses default equality if . /// An observable changeset tracking the single optional item. /// /// @@ -1351,7 +1351,7 @@ public static IObservable> EditDiff(thi /// OnCompletedForwarded to the downstream observer. /// /// - /// or is null. + /// or is . public static IObservable> EditDiff(this IObservable> source, Func keySelector, IEqualityComparer? equalityComparer = null) where TObject : notnull where TKey : notnull @@ -1493,12 +1493,12 @@ public static IObservable> Except(this /// /// Schedules automatic removal of items after the timeout returned by . - /// If returns null, the item never expires. + /// If returns , the item never expires. /// /// The type of the object. /// The type of the key. /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional a function returning the expiration timeout for each item, or for no expiration. /// An observable changeset that includes timer-driven Remove changes for expired items. /// /// When a timer fires, a Remove is emitted for the expired item. @@ -1511,9 +1511,9 @@ public static IObservable> Except(this /// OnErrorForwarded. All pending timers are cancelled. /// OnCompletedForwarded. All pending timers are cancelled. /// - /// Worth noting: A null return from means "never expire". Update changes reset the expiration timer. + /// Worth noting: A return from means "never expire". Update changes reset the expiration timer. /// - /// or is null. + /// or is . public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector) @@ -1525,7 +1525,7 @@ public static IObservable> ExpireAfter( /// /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional a function returning the expiration timeout for each item, or for no expiration. /// the scheduler used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, @@ -1540,7 +1540,7 @@ public static IObservable> ExpireAfter( /// /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional a function returning the expiration timeout for each item, or for no expiration. /// An optional polling interval. If specified, items are expired on a polling interval rather than per-item timers. Less accurate but more efficient when many items share similar expiration times. /// /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next @@ -1559,7 +1559,7 @@ public static IObservable> ExpireAfter( /// /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional a function returning the expiration timeout for each item, or for no expiration. /// A optional if specified, items are expired on a polling interval rather than per-item timers. /// the scheduler used to schedule polling and expiration timers. public static IObservable> ExpireAfter( @@ -1582,16 +1582,16 @@ public static IObservable> ExpireAfter( /// The type of the object. /// The type of the key. /// the source cache from which expired items are removed. - /// A optional a function returning the expiration timeout for each item, or null for no expiration. + /// A optional a function returning the expiration timeout for each item, or for no expiration. /// A optional if specified, items are expired on a polling interval rather than per-item timers. - /// The scheduler used to schedule expiration timers. Defaults to if null. + /// The scheduler used to schedule expiration timers. Defaults to if . /// An observable that emits the key-value pairs of items removed from the cache by expiration. /// /// Unlike the stream-based overloads, this operates directly on the /// and returns the removed items as collections, /// not as a changeset stream. /// - /// or is null. + /// or is . public static IObservable>> ExpireAfter( this ISourceCache source, Func timeSelector, @@ -1613,7 +1613,7 @@ public static IObservable>> ExpireAfter< /// The type of the key. /// the source changeset stream. /// the predicate used to determine whether each item is included. - /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets, which can be useful for monitoring loading status. + /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets, which can be useful for monitoring loading status. /// An observable changeset containing only items that satisfy . /// /// @@ -1665,10 +1665,10 @@ public static IObservable> Filter( /// The type of state value required by . /// The source of . /// a stream of state values to be passed to . - /// a predicate that receives the current state and an item, returning true to include or false to exclude. - /// When true (default), empty changesets are suppressed for performance. Set to false to emit empty changesets. + /// a predicate that receives the current state and an item, returning to include or to exclude. + /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets. /// An observable changeset containing only items satisfying for the latest state. - /// , , or is null. + /// , , or is . /// /// /// should emit an initial value immediately upon subscription. @@ -1704,7 +1704,7 @@ public static IObservable> Filter the source changeset stream. /// an observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. /// an observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. - /// When true (default), empty changesets are suppressed for performance. + /// When (default), empty changesets are suppressed for performance. /// /// In addition to the per-item behavior described in the static overload, /// emissions from replace the predicate and trigger full re-filtering, @@ -1780,17 +1780,17 @@ public static IObservable> FilterImmutableThe type of the object. /// The type of the key. /// The source of . - /// A factory that creates an for each item and its key. When the observable emits true, the item is included; when false, it is excluded. + /// A factory that creates an for each item and its key. When the observable emits , the item is included; when , it is excluded. /// A that optional time window to buffer inclusion changes from per-item observables before re-evaluating. /// An that optional scheduler used for buffering. - /// An observable changeset containing only items whose per-item observable most recently emitted true. + /// An observable changeset containing only items whose per-item observable most recently emitted . /// /// /// Source changeset handling (parent events): /// /// /// EventBehavior - /// AddSubscribes to the per-item observable. The item is not included downstream until the observable emits its first true. + /// AddSubscribes to the per-item observable. The item is not included downstream until the observable emits its first . /// UpdateDisposes the old item's observable subscription and subscribes to the new item's observable. Inclusion state is reset; the new observable must emit before the item reappears. /// RemoveDisposes the item's observable subscription. If the item was included downstream, a Remove is emitted. /// RefreshForwarded as Refresh if the item is currently included downstream. Otherwise dropped. @@ -1800,21 +1800,21 @@ public static IObservable> FilterImmutable /// /// EmissionBehavior - /// First trueThe item is included: an Add is emitted downstream. - /// false (was included)The item is excluded: a Remove is emitted downstream. - /// true (was excluded)The item is re-included: an Add is emitted downstream. - /// true (was included)No effect (already included). - /// false (was excluded)No effect (already excluded). + /// First The item is included: an Add is emitted downstream. + /// (was included)The item is excluded: a Remove is emitted downstream. + /// (was excluded)The item is re-included: an Add is emitted downstream. + /// (was included)No effect (already included). + /// (was excluded)No effect (already excluded). /// ErrorTerminates the entire output stream. /// CompletedThe item remains in its current inclusion state. No further toggling is possible for this item. /// /// - /// Worth noting: Items are invisible downstream until their per-item observable emits at least one true. + /// Worth noting: Items are invisible downstream until their per-item observable emits at least one . /// If an item's observable never emits, the item never appears. The parameter batches /// rapid inclusion changes from per-item observables into a single re-evaluation, reducing changeset chatter. /// /// - /// or is null. + /// or is . /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull @@ -1864,7 +1864,7 @@ public static IObservable FinallySafe(this IObservable source, Action f /// The type of the key. /// the source changeset stream. /// An observable of individual values. - /// is null. + /// is . /// public static IObservable> Flatten(this IObservable> source) where TObject : notnull @@ -1883,7 +1883,7 @@ public static IObservable> Flatten(this IOb /// The type of the key. /// the source observable of buffered changeset lists. /// An observable changeset combining all changes from each buffer into a single emission. - /// is null. + /// is . public static IObservable> FlattenBufferResult(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -1916,7 +1916,7 @@ public static IObservable> FlattenBufferResult propagate as OnError to the subscriber. No try-catch is applied. /// /// - /// or is null. + /// or is . public static IObservable> ForEachChange(this IObservable> source, Action> action) where TObject : notnull where TKey : notnull @@ -1986,7 +1986,7 @@ public static IObservable> FullJoin /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2066,7 +2066,7 @@ public static IObservable> FullJoinMany /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2514,7 +2514,7 @@ public static IObservable> IncludeUpdateWhenThe output is keyed by a (TLeftKey, TRightKey) composite tuple, since a single left item may match multiple right items. /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2593,7 +2593,7 @@ public static IObservable> InnerJoinMany /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2695,7 +2695,7 @@ public static IObservable> LeftJoin /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2774,7 +2774,7 @@ public static IObservable> LeftJoinMany /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -2814,7 +2814,7 @@ public static IObservable> LeftJoinManyOnCompletedForwarded to subscribers. /// /// - /// is null. + /// is . /// is zero or negative. public static IObservable> LimitSizeTo(this IObservable> source, int size) where TObject : notnull @@ -2840,7 +2840,7 @@ public static IObservable> LimitSizeTo( /// The maximum number of items allowed. Must be greater than zero. /// Optional scheduler for observing changes. Defaults to . /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. - /// is null. + /// is . /// is zero or negative. public static IObservable>> LimitSizeTo(this ISourceCache source, int sizeLimit, IScheduler? scheduler = null) where TObject : notnull @@ -2956,7 +2956,7 @@ public static IObservable MergeMany(t /// pair (source + other, exactly two streams), or static (, all sources known up front). /// (2) Conflict resolution: none (first-in-wins), (lowest-ordered wins), /// (suppresses duplicate updates), or both. - /// (3) Completion: static overloads accept a completable flag; when false, the output never completes + /// (3) Completion: static overloads accept a completable flag; when , the output never completes /// even after all sources finish (useful for "live" merge scenarios). /// /// @@ -2966,7 +2966,7 @@ public static IObservable MergeMany(t /// RemoveIf the removed value was the one published downstream, the operator scans all remaining sources for the same key. If another source still holds that key, an Update is emitted with the replacement value (selected by comparer if provided, otherwise the next available). If no other source holds the key, a Remove is emitted. /// RefreshIf the refreshed item matches the currently published value, the Refresh is forwarded. With a comparer, all sources are re-evaluated first; if a different value now wins, an Update is emitted instead of the Refresh. /// OnErrorAn error from any source (outer or inner) terminates the entire merged output. - /// OnCompletedFor dynamic overloads, the output completes when the outer observable completes and all subscribed inner observables have also completed. For static overloads, completion depends on the completable parameter (default true). + /// OnCompletedFor dynamic overloads, the output completes when the outer observable completes and all subscribed inner observables have also completed. For static overloads, completion depends on the completable parameter (default ). /// /// /// Worth noting: When a source removes a key that was published downstream, the fallback to another @@ -2975,7 +2975,7 @@ public static IObservable MergeMany(t /// stream, so consider error handling within individual sources if isolation is needed. /// /// - /// is null. + /// is . /// /// public static IObservable> MergeChangeSets(this IObservable>> source) @@ -3060,7 +3060,7 @@ public static IObservable> MergeChangeSets the first changeset stream. /// the second changeset stream to merge with . /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IScheduler? scheduler = null, bool completable = true) @@ -3082,7 +3082,7 @@ public static IObservable> MergeChangeSets the second changeset stream to merge with . /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3105,7 +3105,7 @@ public static IObservable> MergeChangeSets the second changeset stream to merge with . /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) @@ -3129,7 +3129,7 @@ public static IObservable> MergeChangeSetsAn that equality comparer to detect duplicate values for the same key. /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when both streams complete. If false, the output never completes. + /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IObservable> other, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3153,7 +3153,7 @@ public static IObservable> MergeChangeSets the primary changeset stream. /// An that additional changeset streams to merge with . /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IScheduler? scheduler = null, bool completable = true) @@ -3175,7 +3175,7 @@ public static IObservable> MergeChangeSetsAn that additional changeset streams to merge with . /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3198,7 +3198,7 @@ public static IObservable> MergeChangeSetsAn that additional changeset streams to merge with . /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) @@ -3222,7 +3222,7 @@ public static IObservable> MergeChangeSetsAn that equality comparer to detect duplicate values for the same key. /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all streams complete. If false, the output never completes. + /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , , or is null. public static IObservable> MergeChangeSets(this IObservable> source, IEnumerable>> others, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3245,7 +3245,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying items. /// the collection of changeset streams to merge. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// /// @@ -3278,7 +3278,7 @@ public static IObservable> MergeChangeSets the collection of changeset streams to merge. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3301,7 +3301,7 @@ public static IObservable> MergeChangeSets the collection of changeset streams to merge. /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IScheduler? scheduler = null, bool completable = true) @@ -3324,7 +3324,7 @@ public static IObservable> MergeChangeSetsAn that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. - /// If true (default), the output completes when all source streams have completed. If false, the output never completes. + /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// , , or is null. public static IObservable> MergeChangeSets(this IEnumerable>> source, IEqualityComparer equalityComparer, IComparer comparer, IScheduler? scheduler = null, bool completable = true) @@ -3471,7 +3471,7 @@ public static IObservable> MergeManyCh /// Update for an already-published key is suppressed when the new value equals the old. /// /// - /// or is null. + /// or is . /// /// /// @@ -3547,7 +3547,7 @@ public static IObservable> MergeManyCh /// the source cache changeset stream. /// A that factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. @@ -3574,7 +3574,7 @@ public static IObservable> MergeManyCh /// the source cache changeset stream. /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. @@ -3644,7 +3644,7 @@ public static IObservable> MergeManyCh /// the source cache changeset stream. /// A that factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. - /// If true, a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. @@ -3674,7 +3674,7 @@ public static IObservable> MergeManyCh /// the source cache changeset stream. /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// If true (default), a Refresh in the source stream re-evaluates source priorities. If false, Refresh events are ignored for priority recalculation. + /// If (default), a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. /// An that optional fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. @@ -3788,7 +3788,7 @@ public static IObservable> MergeManyItemsThe type of the source observable. /// the source observable to monitor. /// An observable that emits values reflecting the source's lifecycle. - /// is null. + /// is . /// public static IObservable MonitorStatus(this IObservable source) => new StatusMonitor(source).Run(); @@ -3799,7 +3799,7 @@ public static IObservable> MergeManyItemsThe type of the key. /// the source changeset stream. /// An observable that emits only non-empty changesets. - /// is null. + /// is . /// public static IObservable> NotEmpty(this IObservable> source) where TObject : notnull @@ -3818,7 +3818,7 @@ public static IObservable> NotEmpty(thi /// The type of the key. /// The destination type to filter and cast to. /// the source observable changeset. - /// If true, changesets that become empty after filtering are suppressed. + /// If , changesets that become empty after filtering are suppressed. /// An observable changeset of items. /// /// @@ -3831,7 +3831,7 @@ public static IObservable> NotEmpty(thi /// OnCompletedForwarded to subscribers. /// /// - /// is null. + /// is . public static IObservable> OfType(this IObservable> source, bool suppressEmptyChangeSets = true) where TObject : notnull where TKey : notnull @@ -3865,7 +3865,7 @@ public static IObservable> OfType propagate as OnError. No try-catch is applied. /// /// - /// or is null. + /// or is . /// /// /// @@ -3911,7 +3911,7 @@ public static IObservable> OnItemAdded( /// Exceptions thrown in propagate as OnError. No try-catch is applied. /// /// - /// or is null. + /// or is . /// public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull @@ -3941,8 +3941,8 @@ public static IObservable> OnItemRefreshedThe source of . /// the callback invoked for each removed item. Receives the removed item and its key. /// - /// When true (the default), the callback is also invoked for every item still in the cache - /// when the subscription is disposed. When false, only inline Remove changes trigger the callback. + /// When (the default), the callback is also invoked for every item still in the cache + /// when the subscription is disposed. When , only inline Remove changes trigger the callback. /// /// A stream that forwards all changesets from unchanged. /// @@ -3950,14 +3950,14 @@ public static IObservable> OnItemRefreshedChange reason handling: /// /// EventBehavior - /// AddIgnored (but tracked internally when is true). - /// UpdateIgnored (cache updated internally when is true). + /// AddIgnored (but tracked internally when is ). + /// UpdateIgnored (cache updated internally when is ). /// RemoveInvokes with the item and key. /// RefreshIgnored. /// /// /// - /// Unsubscribe behavior: when is true, the operator + /// Unsubscribe behavior: when is , the operator /// maintains an internal cache mirroring the stream. On disposal, it iterates all remaining items and /// invokes for each. This is useful for cleanup logic (e.g. event unsubscription) /// that must run for items that were never explicitly removed. @@ -3966,9 +3966,9 @@ public static IObservable> OnItemRefreshed propagate as OnError during inline removes. /// During unsubscribe disposal, exceptions are not caught. /// - /// Worth noting: The action also fires for ALL remaining items when the subscription is disposed (unless invokeOnUnsubscribe is false). The action runs under a lock; avoid calling into other caches from within it. + /// Worth noting: The action also fires for ALL remaining items when the subscription is disposed (unless invokeOnUnsubscribe is ). The action runs under a lock; avoid calling into other caches from within it. /// - /// or is null. + /// or is . /// /// public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) @@ -3989,7 +3989,7 @@ public static IObservable> OnItemRemoved /// the source changeset stream. /// the callback invoked for each removed item. Receives only the item (no key). - /// When true (the default), also invoked for all remaining items on disposal. + /// When (the default), also invoked for all remaining items on disposal. /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull @@ -4020,7 +4020,7 @@ public static IObservable> OnItemRemoved propagate as OnError. No try-catch is applied. /// /// - /// or is null. + /// or is . /// /// public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) @@ -4065,7 +4065,7 @@ public static IObservable> OnItemUpdatedOnCompletedThe output completes when all sources have completed. /// /// - /// or is null. + /// or is . /// /// /// @@ -4158,7 +4158,7 @@ public static IObservable> Or(this IObs /// /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. /// - /// or is null. + /// or is . /// /// public static IDisposable PopulateFrom(this ISourceCache source, IObservable> observable) @@ -4178,7 +4178,7 @@ public static IDisposable PopulateFrom(this ISourceCache the source cache to populate. /// the observable that emits individual items. /// An that, when disposed, unsubscribes from . - /// or is null. + /// or is . public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) where TObject : notnull where TKey : notnull @@ -4210,7 +4210,7 @@ public static IDisposable PopulateFrom(this ISourceCacheOnCompletedThe subscription ends. The destination cache retains all items. /// /// - /// or is null. + /// or is . /// /// public static IDisposable PopulateInto(this IObservable> source, ISourceCache destination) @@ -4273,7 +4273,7 @@ public static IDisposable PopulateInto(this IObservable /// Worth noting: The selector is called on every changeset, which can be chatty. The exposes the full cache state for LINQ-style queries. /// - /// or is null. + /// or is . /// /// public static IObservable QueryWhenChanged(this IObservable> source, Func, TDestination> resultSelector) @@ -4356,7 +4356,7 @@ public static IObservable> RefCount(thi /// OtherNo Add, Update, or Remove events are produced by this method. /// /// - /// is null. + /// is . /// /// public static void Refresh(this ISourceCache source, TObject item) @@ -4375,7 +4375,7 @@ public static void Refresh(this ISourceCache sourc /// The type of the key. /// the source cache. /// the items to refresh. - /// is null. + /// is . public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -4391,7 +4391,7 @@ public static void Refresh(this ISourceCache sourc /// The type of the object. /// The type of the key. /// the source cache. - /// is null. + /// is . public static void Refresh(this ISourceCache source) where TObject : notnull where TKey : notnull @@ -4416,7 +4416,7 @@ public static void Refresh(this ISourceCache sourc /// OtherNo Add, Update, or Refresh events are produced by this method. /// /// - /// is null. + /// is . /// /// /// @@ -4436,7 +4436,7 @@ public static void Remove(this ISourceCache source /// The type of the key. /// the source cache. /// The key of the item to remove. - /// is null. + /// is . public static void Remove(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -4454,7 +4454,7 @@ public static void Remove(this ISourceCache source /// The type of the key. /// the source cache. /// the items to remove. - /// is null. + /// is . public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull where TKey : notnull @@ -4472,7 +4472,7 @@ public static void Remove(this ISourceCache source /// The type of the key. /// the source cache. /// the keys to remove. - /// is null. + /// is . public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -4538,7 +4538,7 @@ public static IObservable> RemoveKey(this IOb /// The type of the key. /// the source cache. /// The key to remove. - /// is null. + /// is . public static void RemoveKey(this ISourceCache source, TKey key) where TObject : notnull where TKey : notnull @@ -4555,7 +4555,7 @@ public static void RemoveKey(this ISourceCache sou /// The type of the key. /// the source cache. /// the keys to remove. - /// is null. + /// is . public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull where TKey : notnull @@ -4624,7 +4624,7 @@ public static IObservable> RightJoin /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -4704,7 +4704,7 @@ public static IObservable> RightJoinMany /// Both sources are serialized through a shared lock held during downstream delivery. Avoid blocking operations in subscribers. /// - /// Any argument is null. + /// Any argument is . /// /// /// @@ -4732,7 +4732,7 @@ public static IObservable> RightJoinManyThe type of the key. /// the source changeset stream. /// An observable that skips the first changeset and forwards all others. - /// is null. + /// is . /// /// public static IObservable> SkipInitial(this IObservable> source) @@ -5000,7 +5000,7 @@ public static IObservable> StartWithItem /// - /// or is null. + /// or is . /// /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) @@ -5100,11 +5100,11 @@ public static IObservable> ToCollectionThe type of the key. /// the source observable of individual items. /// A that selects the unique key for each item. - /// A optional optional: per-item expiration time. Return null for no expiration. + /// A optional optional: per-item expiration time. Return for no expiration. /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional optional scheduler for expiration timing. /// An observable changeset stream. - /// or is null. + /// or is . public static IObservable> ToObservableChangeSet( this IObservable source, Func keySelector, @@ -5134,11 +5134,11 @@ public static IObservable> ToObservableChangeSetThe type of the key. /// the source observable of item batches. /// A that selects the unique key for each item. - /// A optional optional: per-item expiration time. Return null for no expiration. + /// A optional optional: per-item expiration time. Return for no expiration. /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional optional scheduler for expiration timing. /// An observable changeset stream. - /// or is null. + /// or is . public static IObservable> ToObservableChangeSet( this IObservable> source, Func keySelector, @@ -5167,7 +5167,7 @@ public static IObservable> ToObservableChangeSetThe type of the key. /// The source of . /// The key to watch. - /// An that optional comparer to suppress duplicate emissions. Uses default equality if null. + /// An that optional comparer to suppress duplicate emissions. Uses default equality if . /// An observable of that reflects the presence or absence of the specified key. /// /// @@ -5185,7 +5185,7 @@ public static IObservable> ToObservableChangeSet /// Worth noting: No emission occurs if the key is not present at subscription time. To get an initial None when the key is absent, use the overload with initialOptionalWhenMissing: true. /// - /// is null. + /// is . /// /// public static IObservable> ToObservableOptional(this IObservable> source, TKey key, IEqualityComparer? equalityComparer = null) @@ -5263,7 +5263,7 @@ public static IObservable> ToSortedCollection - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. + /// This overload accepts a bool transformOnRefresh flag. When , Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5276,7 +5276,7 @@ public static IObservable> Transform - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). The factory receives the current item and key. + /// This overload accepts a bool transformOnRefresh flag. When , Refresh changes cause re-transformation (emitted as Update). The factory receives the current item and key. public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5289,7 +5289,7 @@ public static IObservable> Transform - /// This overload accepts a bool transformOnRefresh flag. When true, Refresh changes cause re-transformation (emitted as Update). + /// This overload accepts a bool transformOnRefresh flag. When , Refresh changes cause re-transformation (emitted as Update). public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5335,7 +5335,7 @@ public static IObservable> TransformThe type of the key. /// The source of . /// a function that produces a from the current source item, the previous source item (if any), and the key. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. /// /// @@ -5364,7 +5364,7 @@ public static IObservable> Transform /// /// - /// or is null. + /// or is . public static IObservable> Transform(this IObservable> source, Func, TKey, TDestination> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -5452,7 +5452,7 @@ public static IObservable> TransformAsyncThe type of the key. /// The source of . /// an async function that produces a from the current source item, the previous source item (if any), and the key. - /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. Re-transformed items are emitted as changes. If null, no forced re-transforms occur. + /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. /// /// @@ -5475,7 +5475,7 @@ public static IObservable> TransformAsync /// - /// or is null. + /// or is . [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func, TKey, Task> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -5555,7 +5555,7 @@ public static IObservable> TransformAsync /// Use this when items are immutable, the factory is pure, and the factory is cheap. If any of these conditions are false, use instead. /// - /// or is null. + /// or is . public static IObservable> TransformImmutable( this IObservable> source, Func transformFactory) @@ -5596,7 +5596,7 @@ public static IObservable> TransformImmutableWorth noting: If two source items produce children with the same key, last-in-wins. Refresh does NOT re-expand children (only Update does). /// If two parents produce children with the same key, last-in-wins. Use the async variant with a to control conflict resolution. /// - /// , , or is null. + /// , , or is . /// public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull @@ -5653,7 +5653,7 @@ public static IObservable> TransformMa /// to catch errors without killing the stream. /// /// - /// or is null. + /// or is . [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManyAsync(this IObservable> source, Func>> manySelector, Func keySelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5746,7 +5746,7 @@ public static IObservable> TransformMa /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. /// An observable changeset of flattened child items. /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. - /// , , or is null. + /// , , or is . [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformManySafeAsync(this IObservable> source, Func>> manySelector, Func keySelector, Action> errorHandler, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) where TDestination : notnull @@ -5864,7 +5864,7 @@ public static IObservable> TransformMa /// also completed. /// /// - /// or is null. + /// or is . /// /// /// @@ -5929,7 +5929,7 @@ public static IObservable> TransformSafe the source changeset observable. /// a function that produces a from the current source item, the previous source item (if any), and the key. /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. - /// An optional an observable that, when it emits a predicate, re-transforms all items for which the predicate returns true. If null, no forced re-transforms occur. + /// An optional an observable that, when it emits a predicate, re-transforms all items for which the predicate returns . If , no forced re-transforms occur. /// An observable changeset of transformed items. /// /// @@ -5939,7 +5939,7 @@ public static IObservable> TransformSafe /// Worth noting: Factory exceptions are caught per-item; the faulting item is skipped and reported to the error handler while the stream continues. Source-level errors still terminate the stream. /// - /// , , or is null. + /// , , or is . public static IObservable> TransformSafe(this IObservable> source, Func, TKey, TDestination> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull where TSource : notnull @@ -6034,7 +6034,7 @@ public static IObservable> TransformSafeAsyncAn optional optional observable to force re-transformation of matching items. /// An observable changeset of transformed items. /// Combines the async execution model of with the error-safe behavior of . - /// , , or is null. + /// , , or is . [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformSafeAsync(this IObservable> source, Func, TKey, Task> transformFactory, Action> errorHandler, IObservable>? forceTransform = null) where TDestination : notnull @@ -6114,7 +6114,7 @@ public static IObservable> TransformSafeAsync /// Circular references are NOT detected. If item A is the parent of B and B is the parent of A, behavior is undefined. /// - /// or is null. + /// or is . public static IObservable, TKey>> TransformToTree(this IObservable> source, Func pivotOn, IObservable, bool>>? predicateChanged = null) where TObject : class where TKey : notnull @@ -6179,7 +6179,7 @@ public static IObservable> TransformWithInlineUpd /// A that called on Add (and optionally Refresh) to create a new . /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. /// A that called when or throws. The faulting item is skipped. - /// When true, Refresh changes call on the existing item. + /// When , Refresh changes call on the existing item. /// An observable changeset of transformed items. /// /// @@ -6195,7 +6195,7 @@ public static IObservable> TransformWithInlineUpd /// RefreshIf is true, calls . Otherwise forwarded as Refresh. /// /// - /// , , , or is null. + /// , , , or is . public static IObservable> TransformWithInlineUpdate(this IObservable> source, Func transformFactory, Action updateAction, Action> errorHandler, bool transformOnRefresh) where TDestination : class where TSource : notnull @@ -6243,8 +6243,8 @@ static IEnumerable> ReplaceMoves(IChangeSet } /// - /// Emits true when all items in the cache satisfy a condition based on their per-item observable, - /// and false otherwise. Re-evaluates whenever the cache changes or any per-item observable emits. + /// Emits when all items in the cache satisfy a condition based on their per-item observable, + /// and otherwise. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. @@ -6253,7 +6253,7 @@ static IEnumerable> ReplaceMoves(IChangeSet /// A that factory that produces a condition observable for each item. /// A that predicate applied to each per-item observable's latest value. /// An observable of bool that emits whenever the all-items condition changes. - /// , , or is null. + /// , , or is . /// /// /// EventBehavior @@ -6264,7 +6264,7 @@ static IEnumerable> ReplaceMoves(IChangeSet /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. /// OnCompletedCompletes when the source and all per-item observables have completed. /// - /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache is vacuously true. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache is vacuously . The result uses DistinctUntilChanged, so duplicate bool values are suppressed. /// /// public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -6296,8 +6296,8 @@ public static IObservable TrueForAll(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.All(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// Emits true when any item in the cache satisfies a condition based on its per-item observable, - /// and false when none do. Re-evaluates whenever the cache changes or any per-item observable emits. + /// Emits when any item in the cache satisfies a condition based on its per-item observable, + /// and when none do. Re-evaluates whenever the cache changes or any per-item observable emits. /// /// The type of the object. /// The type of the key. @@ -6306,7 +6306,7 @@ public static IObservable TrueForAll(this IObservab /// A that factory that produces a condition observable for each item. /// A that predicate applied to each item and its per-item observable's latest value. /// An observable of bool that emits whenever the any-item condition changes. - /// , , or is null. + /// , , or is . /// /// /// EventBehavior @@ -6317,7 +6317,7 @@ public static IObservable TrueForAll(this IObservab /// OnErrorAn error from any per-item observable terminates the entire stream. Source errors also terminate. /// OnCompletedCompletes when the source and all per-item observables have completed. /// - /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache yields false. The result uses DistinctUntilChanged, so duplicate bool values are suppressed. + /// Worth noting: Items whose per-item observable has not yet emitted are treated as not satisfying the condition. An empty cache yields . The result uses DistinctUntilChanged, so duplicate bool values are suppressed. /// /// public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -6479,7 +6479,7 @@ public static IObservable WatchValue(this IObservableThe type of the monitored property. /// The source of . /// A that expression selecting the property to monitor. - /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of containing both the item and its property value. /// /// @@ -6516,7 +6516,7 @@ public static IObservable> WhenPropertyChangedThe type of the monitored property. /// The source of . /// A that expression selecting the property to monitor. - /// When true (the default), the current property value is emitted immediately for each item upon subscription. + /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of property values. The owning item is not included; use if you need it. /// /// @@ -6631,7 +6631,7 @@ public static IObservable> WhereReasonsAreNotOnCompletedThe output completes when all sources have completed. /// /// - /// or is null. + /// or is . /// /// /// From 9becc5685f71bec72172c3e12ecf96093b63e9ac Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:46:48 -0700 Subject: [PATCH 16/23] docs: add cross-file seealso between cache and list operators RemoveKey now links to ObservableListEx.AddKey (the inverse operation that converts list changesets to cache changesets by adding keys). --- src/DynamicData/Cache/ObservableCacheEx.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 181f03687..849303c38 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -4516,6 +4516,7 @@ public static void Remove(this IIntermediateCache /// The type of the key. /// the source changeset stream. /// A list changeset stream without key information. + /// /// public static IObservable> RemoveKey(this IObservable> source) where TObject : notnull From 93485ce4205913d6da07eadcea8ce24e78b3c428 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 10:51:55 -0700 Subject: [PATCH 17/23] docs: add cross-links from cache operators to list equivalents 27 primary cache operators now link to their list counterpart via seealso, enabling navigation between the two collection types in generated docs. --- src/DynamicData/Cache/ObservableCacheEx.cs | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 849303c38..6d2c6d701 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -176,6 +176,7 @@ public static void AddOrUpdate(this IIntermediateCache the others. /// An observable which emits change sets. /// source or others. + /// public static IObservable> And(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -375,6 +376,7 @@ public static IObservable> AsyncDisposeManyA optional when observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. /// An optional the scheduler. /// An observable change set with additional refresh changes. + /// public static IObservable> AutoRefresh(this IObservable> source, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged where TKey : notnull @@ -438,6 +440,7 @@ public static IObservable> AutoRefreshA optional batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. /// An optional the scheduler. /// An observable change set with additional refresh changes. + /// public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull => source.AutoRefreshOnObservable((t, _) => reevaluator(t), changeSetBuffer, scheduler); @@ -584,6 +587,7 @@ public static IObservable> BatchIf(this /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. /// source. + /// public static IObservable> Bind(this IObservable> source, IObservableCollection destination, int refreshThreshold = BindingOptions.DefaultResetThreshold) where TObject : notnull where TKey : notnull @@ -1210,6 +1214,7 @@ public static IObservable> DeferUntilLoaded is . /// /// + /// public static IObservable> DisposeMany(this IObservable> source) where TObject : notnull where TKey : notnull @@ -1233,6 +1238,7 @@ public static IObservable> DisposeMany( /// Worth noting: Reference counting assumes value equality is transitive. Mutable value objects with inconsistent Equals implementations can corrupt ref counts. /// /// source. + /// public static IObservable> DistinctValues(this IObservable> source, Func valueSelector) where TObject : notnull where TKey : notnull @@ -1404,6 +1410,7 @@ public static IObservable> EnsureUniqueKeys + /// public static IObservable> Except(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -1629,6 +1636,7 @@ public static IObservable>> ExpireAfter< /// /// /// + /// public static IObservable> Filter( this IObservable> source, Func filter, @@ -1816,6 +1824,7 @@ public static IObservable> FilterImmutable /// or is . /// + /// public static IObservable> FilterOnObservable(this IObservable> source, Func> filterFactory, TimeSpan? buffer = null, IScheduler? scheduler = null) where TObject : notnull where TKey : notnull @@ -1917,6 +1926,7 @@ public static IObservable> FlattenBufferResult /// /// or is . + /// public static IObservable> ForEachChange(this IObservable> source, Action> action) where TObject : notnull where TKey : notnull @@ -2908,6 +2918,7 @@ public static IObservable>> LimitSizeTo< /// /// /// + /// public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -2978,6 +2989,7 @@ public static IObservable MergeMany(t /// is . /// /// + /// public static IObservable> MergeChangeSets(this IObservable>> source) where TObject : notnull where TKey : notnull @@ -3352,6 +3364,7 @@ public static IObservable> MergeChangeSetsAn that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// or is null. + /// public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) where TObject : notnull where TKey : notnull @@ -3869,6 +3882,7 @@ public static IObservable> OfType /// /// + /// public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull where TKey : notnull @@ -3913,6 +3927,7 @@ public static IObservable> OnItemAdded( /// /// or is . /// + /// public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull where TKey : notnull @@ -3971,6 +3986,7 @@ public static IObservable> OnItemRefreshed or is . /// /// + /// public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) where TObject : notnull where TKey : notnull @@ -4070,6 +4086,7 @@ public static IObservable> OnItemUpdated /// /// + /// public static IObservable> Or(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull @@ -4276,6 +4293,7 @@ public static IDisposable PopulateInto(this IObservable or is . /// /// + /// public static IObservable QueryWhenChanged(this IObservable> source, Func, TDestination> resultSelector) where TObject : notnull where TKey : notnull @@ -4760,6 +4778,7 @@ public static IObservable> SkipInitial( /// or /// comparer. /// + /// [Obsolete(Constants.SortIsObsolete)] public static IObservable> Sort(this IObservable> source, IComparer comparer, SortOptimisations sortOptimisations = SortOptimisations.None, int resetThreshold = DefaultSortResetThreshold) where TObject : notnull @@ -5004,6 +5023,7 @@ public static IObservable> StartWithItem or is . /// /// + /// public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull where TKey : notnull @@ -5265,6 +5285,7 @@ public static IObservable> ToSortedCollection /// This overload accepts a bool transformOnRefresh flag. When , Refresh changes cause re-transformation (emitted as Update). The factory receives only the current item. + /// public static IObservable> Transform(this IObservable> source, Func transformFactory, bool transformOnRefresh) where TDestination : notnull where TSource : notnull @@ -5418,6 +5439,7 @@ public static IObservable> Transform /// This overload takes a simpler factory that receives only the current item. + /// [SuppressMessage("Roslynator", "RCS1047:Non-asynchronous method name should not end with 'Async'.", Justification = "By Design.")] public static IObservable> TransformAsync(this IObservable> source, Func> transformFactory, IObservable>? forceTransform = null) where TDestination : notnull @@ -5599,6 +5621,7 @@ public static IObservable> TransformImmutable /// , , or is . /// + /// public static IObservable> TransformMany(this IObservable> source, Func> manySelector, Func keySelector) where TDestination : notnull where TDestinationKey : notnull @@ -6462,6 +6485,7 @@ public static IObservable WatchValue(this IObservable /// /// + /// public static IObservable WhenAnyPropertyChanged(this IObservable> source, params string[] propertiesToMonitor) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6498,6 +6522,7 @@ public static IObservable WatchValue(this IObservableOnCompletedCompletes when the source changeset stream completes. /// /// + /// public static IObservable> WhenPropertyChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6538,6 +6563,7 @@ public static IObservable> WhenPropertyChanged /// /// + /// public static IObservable WhenValueChanged(this IObservable> source, Expression> propertyAccessor, bool notifyOnInitialValue = true) where TObject : INotifyPropertyChanged where TKey : notnull @@ -6636,6 +6662,7 @@ public static IObservable> WhereReasonsAreNot /// /// + /// public static IObservable> Xor(this IObservable> source, params IObservable>[] others) where TObject : notnull where TKey : notnull From 47c3748186c771fa732b3bcac50adec942e344b4 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 11:33:53 -0700 Subject: [PATCH 18/23] Fix param descriptions: proper English with type links, fix Optional.None cref, update skill - Rewrite 470+ param descriptions to read as natural English with type links woven in - Fix double-brace cref syntax ({{T}} to {T}) - Fix wrong types in cref attributes (IObservable{T} to actual parameter types) - Fix meaningless descriptions (the destination, the updater) with specific text - Fix double-description patterns (that The) - Link Optional.None references as - Fix useReplaceForUpdates, resorter, regrouper, forceTransform params - Update documentation skill with comprehensive param writing guidance --- .github/skills/add-documentation/SKILL.md | 27 +- .../Cache/ObservableCacheEx.SortAndBind.cs | 16 +- .../ObservableCacheEx.VirtualiseAndPage.cs | 22 +- src/DynamicData/Cache/ObservableCacheEx.cs | 986 +++++++++--------- 4 files changed, 537 insertions(+), 514 deletions(-) diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md index 674651987..f7db50b31 100644 --- a/.github/skills/add-documentation/SKILL.md +++ b/.github/skills/add-documentation/SKILL.md @@ -126,11 +126,34 @@ Refresh behavior varies significantly between operators: some re-evaluate (Filte ### 3. Apply Quality Rules -**Params**: Every `` links its type via ``. Exempt: `bool`, `int`, `string`. +**Params**: Every `` must read as natural English with the type linked via `` woven into the sentence. No type is exempt from linking (including enums, `Optional`, `Change`, `IChangeSet`, standard library types like `IComparer`, `TimeSpan`, `IScheduler`). Use `` / `` / `` for C# keywords. + +Param writing rules: +- Start with an article ("The", "A", "An") or a condition ("When", "If") +- The type link appears naturally in the sentence, not as a prefix dumped before the description +- Never echo the parameter name as the entire description ("The source.", "The destination.") +- For `IObservable>` source params, use the two-part format: `The source of .` +- For deeply nested generics (3+ levels), use `{T}` in the cref and describe the actual type in prose +- For `params` array parameters, do not include `[]` in the cref. Mention "array" in prose if needed. +- For `Optional.None` references, use `` + +```xml + +/// the source. +/// the destination. +/// A that The binding options. + + +/// The source of . +/// The that will receive the changes. +/// The that controls binding behavior. +/// An optional for scheduling work. +/// The used to determine whether a new item is the same as an existing cached item. +``` **SeeAlso**: Bidirectional for overload sets. Link safe/async/immutable variants, similar operators, complementary operators, commonly confused operators. -**Type references**: Types use ``. Method/event/property names use `...`. Internal types must not appear; describe behavior instead. +**Type references**: All types use ``, including enums, structs, and standard library types. Method/event/property names use `...`. Internal types must not appear; describe behavior instead. **Tone**: No em dashes. No emoji. No filler words (comprehensive, robust, seamlessly, leverage, utilize, facilitate). Be specific: "an **Update** is emitted" not "the change is propagated". Use "Worth noting" for non-obvious behavior. diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index 7cb3afb04..b92009853 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -41,7 +41,7 @@ public static partial class ObservableCacheEx /// The type of the key. /// The source changeset stream. /// The resulting read only observable collection. - /// Bind and sort default options. + /// The with default settings. /// An observable which will emit change sets. /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -80,7 +80,7 @@ public static partial class ObservableCacheEx /// The type of the key. /// The source changeset stream. /// The list to bind to. - /// Bind and sort default options. + /// The with default settings. /// An observable which will emit change sets. /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -119,7 +119,7 @@ public static partial class ObservableCacheEx /// The type of the key. /// The source changeset stream. /// The resulting read only observable collection. - /// Bind and sort default options. + /// The with default settings. /// An observable which will emit change sets. /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -158,7 +158,7 @@ public static partial class ObservableCacheEx /// The type of the key. /// The source changeset stream. /// The list to bind to. - /// Bind and sort default options. + /// The with default settings. /// An observable which will emit change sets. /// This overload accepts to control reset threshold behavior. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -207,7 +207,7 @@ public static partial class ObservableCacheEx /// The source changeset stream. /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. /// The comparer to order the resulting dataset. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The controlling reset threshold and initial capacity. /// An observable which will emit change sets. /// /// @@ -253,7 +253,7 @@ public static partial class ObservableCacheEx /// The source changeset stream. /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. /// An observable of comparers which enables the sort order to be changed. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The controlling reset threshold and initial capacity. /// An observable which will emit change sets. /// /// @@ -313,7 +313,7 @@ public static partial class ObservableCacheEx /// The source changeset stream. /// The resulting read only observable collection. /// The comparer to order the resulting dataset. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, @@ -345,7 +345,7 @@ public static partial class ObservableCacheEx /// The source changeset stream. /// The resulting read only observable collection. /// An observable of comparers which enables the sort order to be changed. - /// Bind and sort options controlling reset threshold and initial capacity. + /// The controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index 6aa4caa9b..f02aa8004 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -45,7 +45,7 @@ public static IObservable>> So /// The source changeset stream. /// The comparer to order the resulting dataset. /// The virtualizing requests (start index and page size). - /// Additional optimization options for virtualization. + /// The for controlling virtualization behavior. /// An observable which will emit virtual change sets. /// source. /// @@ -89,7 +89,7 @@ public static IObservable>> So /// The source changeset stream. /// An observable of comparers which enables the sort order to be changed. /// The virtualizing requests (start index and page size). - /// Additional optimization options for virtualization. + /// The for controlling virtualization behavior. /// An observable which will emit virtual change sets. /// source. /// @@ -129,8 +129,8 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the virtualising requests. + /// The source of . + /// The virtualising requests. /// An observable which will emit virtual change sets. /// source. [Obsolete(Constants.VirtualizeIsObsolete)] @@ -150,8 +150,8 @@ public static IObservable> Virtualise /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the comparer. + /// The source of . + /// The used to determine sort order. /// The maximum number of items to return. /// An observable which will emit virtual change sets. /// source. @@ -184,7 +184,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The size. /// An observable which will emit virtual change sets. /// source. @@ -237,7 +237,7 @@ public static IObservable>> SortA /// The source changeset stream. /// The comparer to order the resulting dataset. /// The page requests (page number and page size). - /// Additional optimization options for paging. + /// The for controlling paging behavior. /// An observable which will emit paged change sets. /// source. /// @@ -280,7 +280,7 @@ public static IObservable>> SortA /// The source changeset stream. /// An observable of comparers which enables the sort order to be changed. /// The page requests (page number and page size). - /// Additional optimization options for paging. + /// The for controlling paging behavior. /// An observable which will emit paged change sets. /// source. /// @@ -319,8 +319,8 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the page requests. + /// The source of . + /// The page requests. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] public static IObservable> Page(this IObservable> source, IObservable pageRequests) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 6d2c6d701..e50f47acf 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -33,8 +33,8 @@ public static partial class ObservableCacheEx /// /// The type of items in the cache. /// The type of the key. - /// The source of . - /// the adaptor whose Adapt method is called for each changeset. + /// The source of . + /// The whose Adapt method is called for each changeset. /// An observable that emits the same changesets as , after the adaptor has processed each one. /// /// @@ -65,8 +65,8 @@ public static IObservable> Adapt(this I } /// - /// the source sorted changeset stream. - /// the sorted adaptor whose Adapt method is called for each sorted changeset. + /// The source of . + /// The whose Adapt method is called for each changeset. /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) where TObject : notnull @@ -84,7 +84,7 @@ public static IObservable> Adapt(this I /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// The item to add or update. /// /// Convenience method that wraps a single-item mutation inside . @@ -111,9 +111,9 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// the source cache. + /// The to operate on. /// The item to add or update. - /// the equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull @@ -125,8 +125,8 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// the source cache. - /// the items to add or update. + /// The to operate on. + /// The of items items to add or update. /// Batch overload. All items are added/updated inside a single call, producing one changeset. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -138,9 +138,9 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// the source cache. - /// the items to add or update. - /// the equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// The to operate on. + /// The of items items to add or update. + /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull @@ -152,7 +152,7 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// the source intermediate cache. + /// The to operate on. /// The item to add or update. /// The key to associate with the item. /// This overload operates on , which requires an explicit key parameter. @@ -172,8 +172,8 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the others. + /// The source of . + /// The other array of changeset streams to combine with. /// An observable which emits change sets. /// source or others. /// @@ -193,7 +193,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. /// /// source @@ -215,7 +215,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -232,7 +232,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -249,7 +249,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> And(this IObservableList> sources) where TObject : notnull @@ -265,7 +265,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// the source cache to wrap. + /// The to operate on. /// A read-only . /// is . /// @@ -284,7 +284,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// If (default), all cache operations are synchronized. Set to when the caller guarantees single-threaded access. /// A read-only observable cache that reflects the current state of the pipeline. /// @@ -324,7 +324,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of items in the cache. /// The type of the key. - /// The source of . + /// The source of . /// /// /// Invoked once per subscription, providing an that signals when all @@ -371,9 +371,9 @@ public static IObservable> AsyncDisposeMany /// The object of the change set. /// The key of the change set. - /// the source observable. - /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// A optional when observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The source of . + /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements have successive property changes. + /// An optional throttle applied to each item's property change notifications, preventing excessive refresh invocations. /// An optional the scheduler. /// An observable change set with additional refresh changes. /// @@ -403,10 +403,10 @@ public static IObservable> AutoRefresh( /// The object of the change set. /// The key of the change set. /// The type of the property. - /// the source observable. - /// A that specify a property to observe changes. When it changes a Refresh is invoked. - /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements have successive property changes. - /// A optional when observing on multiple property changes, apply a throttle to prevent excessive refresh invocations. + /// The source of . + /// A that specify a property to observe changes. When it changes a Refresh is invoked. + /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements have successive property changes. + /// An optional throttle applied to each item's property change notifications, preventing excessive refresh invocations. /// An optional the scheduler. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, Expression> propertyAccessor, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) @@ -435,9 +435,9 @@ public static IObservable> AutoRefreshThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// the source observable change set. - /// an observable which acts on items within the collection and produces a value when the item should be refreshed. - /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The source of . + /// The observable which acts on items within the collection and produces a value when the item should be refreshed. + /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements require a refresh. /// An optional the scheduler. /// An observable change set with additional refresh changes. /// @@ -451,9 +451,9 @@ public static IObservable> AutoRefreshOnObservableThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// the source observable change set. - /// an observable which acts on items within the collection and produces a value when the item should be refreshed. - /// A optional batch up changes by specifying the buffer. This greatly increases performance when many elements require a refresh. + /// The source of . + /// The observable which acts on items within the collection and produces a value when the item should be refreshed. + /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements require a refresh. /// An optional the scheduler. /// An observable change set with additional refresh changes. /// @@ -475,8 +475,8 @@ public static IObservable> AutoRefreshOnObservable /// The type of the object. /// The type of the key. - /// The source of . - /// the time window for batching. + /// The source of . + /// The time window for batching. /// The scheduler for timing. Defaults to . /// An observable that emits merged changesets, one per time window. /// @@ -531,11 +531,11 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source of . - /// An that when , buffering begins. When , the buffer is flushed. + /// The source of . + /// An that when , buffering begins. When , the buffer is flushed. /// If , starts in a paused (buffering) state. /// A that maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. - /// the scheduler for timeout timing. + /// The for timeout timing. /// An observable that emits changesets, buffered or passthrough depending on pause state. /// /// @@ -567,11 +567,11 @@ public static IObservable> BatchIf(this } /// - /// the source changeset stream. - /// An that when , buffering begins. When , the buffer is flushed. + /// The source of . + /// An that controls buffering: begins buffering, flushes the buffer. /// If , starts in a paused (buffering) state. - /// An optional an observable timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. - /// An optional the scheduler. + /// An optional timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. + /// An optional for scheduling work. /// This overload accepts an explicit timer observable instead of a timeout. public static IObservable> BatchIf(this IObservable> source, IObservable pauseIfTrueSelector, bool initialPauseState = false, IObservable? timer = null, IScheduler? scheduler = null) where TObject : notnull @@ -582,8 +582,8 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. + /// The source of . + /// The that will receive the changes. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. /// source. @@ -610,9 +610,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. - /// A that The binding options. + /// The source of . + /// The that will receive the changes. + /// The that controls binding behavior. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -629,9 +629,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. - /// the updater. + /// The source of . + /// The that will receive the changes. + /// The that applies changes to the bound collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, IObservableCollectionAdaptor updater) @@ -660,9 +660,9 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the resulting read only observable collection. - /// A that The binding options. + /// The source of . + /// The output that will be populated with the results. + /// The that controls binding behavior. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -681,11 +681,11 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the resulting read only observable collection. + /// The source of . + /// The output that will be populated with the results. /// The number of changes before a reset notification is triggered. - /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. - /// An optional specify an adaptor to change the algorithm to update the target collection. + /// When , uses Replace instead of Remove/Add for updates in the bound collection. Not all platforms support replace notifications. + /// An optional that controls how the target collection is updated. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, int resetThreshold = BindingOptions.DefaultResetThreshold, bool useReplaceForUpdates = BindingOptions.DefaultUseReplaceForUpdates, IObservableCollectionAdaptor? adaptor = null) @@ -717,8 +717,8 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. + /// The source of . + /// The that will receive the changes. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination) @@ -736,9 +736,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. - /// A that The binding options. + /// The source of . + /// The that will receive the changes. + /// The that controls binding behavior. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, BindingOptions options) @@ -757,9 +757,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the destination. - /// the updater. + /// The source of . + /// The that will receive the changes. + /// The that applies changes to the bound collection. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, IObservableCollection destination, ISortedObservableCollectionAdaptor updater) @@ -788,9 +788,9 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the resulting read only observable collection. - /// A that The binding options. + /// The source of . + /// The output that will be populated with the results. + /// The that controls binding behavior. /// An observable which will emit change sets. /// source. public static IObservable> Bind(this IObservable> source, out ReadOnlyObservableCollection readOnlyObservableCollection, BindingOptions options) @@ -811,10 +811,10 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the resulting read only observable collection. + /// The source of . + /// The output that will be populated with the results. /// The number of changes before a reset event is called on the observable collection. - /// Use replace instead of remove / add for updates. NB: Some platforms to not support replace notifications for binding. + /// When , uses Replace instead of Remove/Add for updates in the bound collection. Not all platforms support replace notifications. /// An that specify an adaptor to change the algorithm to update the target collection. /// An observable which will emit change sets. /// source. @@ -845,8 +845,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// the source changeset stream. - /// the target binding list. + /// The source of . + /// The that will receive the changes. /// The reset threshold. /// An observable which will emit change sets. /// @@ -869,8 +869,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// the source changeset stream. - /// the target binding list. + /// The source of . + /// The that will receive the changes. /// The reset threshold. /// An observable which will emit change sets. /// @@ -896,8 +896,8 @@ public static IObservable> Bind(this IO /// /// The object type. /// The type of the key. - /// the source change set. - /// the time window to buffer, measured from when the first changeset arrives. + /// The source of . + /// The time window to buffer, measured from when the first changeset arrives. /// The scheduler for timing. Defaults to . /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. /// @@ -927,8 +927,8 @@ public static IObservable> BufferInitialThe type of the source object. /// The type of the key. /// The type of the destination object. - /// the source changeset stream. - /// the conversion function applied to each item. + /// The source of . + /// The conversion function applied to each item. /// An observable changeset of converted items. /// /// @@ -959,8 +959,8 @@ public static IObservable> CastThe type of the object. /// The type of the source key. /// The type of the destination key. - /// the source changeset stream. - /// a function that computes the destination key from the item, e.g. (item) => item.NewId. + /// The source of . + /// The tion that computes the destination key from the item, e.g. (item) => item.NewId. /// An observable changeset with items re-keyed using . /// /// @@ -1016,7 +1016,7 @@ public static IObservable> ChangeKey /// The type of the object. /// The type of the key. - /// the source cache to clear. + /// The to operate on. /// /// /// EventBehavior @@ -1063,8 +1063,8 @@ public static void Clear(this LockFreeObservableCache /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the target collection to which changes are applied. + /// The source of . + /// The target collection to which changes are applied. /// An observable that forwards all changesets from unchanged. /// /// @@ -1120,8 +1120,8 @@ public static IObservable> Clone(this I /// The type of the object. /// The type of the key. /// The type of the destination. - /// the source changeset stream. - /// the conversion factory. + /// The source of . + /// The conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] public static IObservable> Convert(this IObservable> source, Func conversionFactory) @@ -1146,7 +1146,7 @@ public static IObservable> Convert /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable that begins emitting changesets once the first non-empty changeset is received. /// /// @@ -1192,7 +1192,7 @@ public static IObservable> DeferUntilLoaded /// The type of the object. /// The type of the key. - /// The source of . + /// The source of . /// A stream that forwards all changesets from unchanged. /// /// @@ -1230,8 +1230,8 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// the source changeset stream. - /// the value selector. + /// The source of . + /// The value selector. /// An observable which will emit distinct change sets. /// /// Due to it's nature only adds or removes can be returned. @@ -1251,9 +1251,9 @@ public static IObservable> DistinctValues - /// the source cache to diff against. - /// the complete snapshot of items to diff against the cache. - /// An used to determine whether a new item is the same as an existing cached item. + /// The to operate on. + /// The complete snapshot of items to diff against the cache. + /// An used to determine whether a new item is the same as an existing cached item. /// /// This overload uses an instead of a delegate /// to determine item equality. @@ -1275,9 +1275,9 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// the source cache to diff against. - /// the complete snapshot of desired items. - /// a function that returns when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// The to operate on. + /// The complete snapshot of desired items. + /// The tion that returns when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. /// /// /// EventBehavior @@ -1309,9 +1309,9 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// the source observable of item snapshots. - /// a function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if . + /// The source . + /// The tion to extract the unique key from each item. + /// An optional for comparing items. Uses default equality if . /// An observable changeset representing the incremental differences between successive snapshots. /// /// @@ -1342,9 +1342,9 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// the source observable of optional values. - /// a function to extract the unique key from each item. - /// Optional for comparing items. Uses default equality if . + /// The source . + /// The tion to extract the unique key from each item. + /// An optional for comparing items. Uses default equality if . /// An observable changeset tracking the single optional item. /// /// @@ -1374,7 +1374,7 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// the source changeset stream to validate. + /// The source of . /// A changeset stream guaranteed to contain unique keys per changeset. /// /// @@ -1402,8 +1402,8 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the others. + /// The source of . + /// The other array of changeset streams to combine with. /// An observable which emits change sets. /// /// source @@ -1431,7 +1431,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// the sources. + /// The of changeset streams to combine. /// An observable which emits change sets. /// /// source @@ -1453,7 +1453,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1470,7 +1470,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1487,7 +1487,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Except(this IObservableList> sources) where TObject : notnull @@ -1504,8 +1504,8 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or for no expiration. + /// The source of . + /// An optional a function returning the expiration timeout for each item, or for no expiration. /// An observable changeset that includes timer-driven Remove changes for expired items. /// /// When a timer fires, a Remove is emitted for the expired item. @@ -1531,9 +1531,9 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector); /// - /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or for no expiration. - /// the scheduler used to schedule expiration timers. + /// The source of . + /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// The used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1546,8 +1546,8 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or for no expiration. + /// The source of . + /// An optional a function returning the expiration timeout for each item, or for no expiration. /// An optional polling interval. If specified, items are expired on a polling interval rather than per-item timers. Less accurate but more efficient when many items share similar expiration times. /// /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next @@ -1565,10 +1565,10 @@ public static IObservable> ExpireAfter( pollingInterval: pollingInterval); /// - /// the source changeset stream. - /// A optional a function returning the expiration timeout for each item, or for no expiration. - /// A optional if specified, items are expired on a polling interval rather than per-item timers. - /// the scheduler used to schedule polling and expiration timers. + /// The source of . + /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional if specified, items are expired on a polling interval rather than per-item timers. + /// The used to schedule polling and expiration timers. public static IObservable> ExpireAfter( this IObservable> source, Func timeSelector, @@ -1588,9 +1588,9 @@ public static IObservable> ExpireAfter( /// /// The type of the object. /// The type of the key. - /// the source cache from which expired items are removed. - /// A optional a function returning the expiration timeout for each item, or for no expiration. - /// A optional if specified, items are expired on a polling interval rather than per-item timers. + /// The to operate on. + /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional if specified, items are expired on a polling interval rather than per-item timers. /// The scheduler used to schedule expiration timers. Defaults to if . /// An observable that emits the key-value pairs of items removed from the cache by expiration. /// @@ -1618,8 +1618,8 @@ public static IObservable>> ExpireAfter< /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the predicate used to determine whether each item is included. + /// The source of . + /// The predicate used to determine whether each item is included. /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets, which can be useful for monitoring loading status. /// An observable changeset containing only items that satisfy . /// @@ -1671,9 +1671,9 @@ public static IObservable> Filter( /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source of . - /// a stream of state values to be passed to . - /// a predicate that receives the current state and an item, returning to include or to exclude. + /// The source of . + /// The stream of state values to be passed to . + /// The predicate that receives the current state and an item, returning to include or to exclude. /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets. /// An observable changeset containing only items satisfying for the latest state. /// , , or is . @@ -1709,9 +1709,9 @@ public static IObservable> Filter - /// the source changeset stream. - /// an observable that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. - /// an observable that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. + /// The source of . + /// The that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. + /// The that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. /// When (default), empty changesets are suppressed for performance. /// /// In addition to the per-item behavior described in the static overload, @@ -1739,8 +1739,8 @@ public static IObservable> Filter( /// /// The type of collection items to be filtered. /// The type of the key values of each collection item. - /// the source stream of collection items to be filtered. - /// the filtering predicate to be applied to each item. + /// The source of . + /// The filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. /// @@ -1787,7 +1787,7 @@ public static IObservable> FilterImmutable /// The type of the object. /// The type of the key. - /// The source of . + /// The source of . /// A factory that creates an for each item and its key. When the observable emits , the item is included; when , it is excluded. /// A that optional time window to buffer inclusion changes from per-item observables before re-evaluating. /// An that optional scheduler used for buffering. @@ -1853,8 +1853,8 @@ public static IObservable> FilterOnObservableFinally operator instead. /// /// The type contained within the observables. - /// the source changeset stream. - /// the finally action. + /// The source . + /// The finally action. /// An observable which has always a finally action applied. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) @@ -1871,7 +1871,7 @@ public static IObservable FinallySafe(this IObservable source, Action f /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable of individual values. /// is . /// @@ -1890,7 +1890,7 @@ public static IObservable> Flatten(this IOb /// /// The type of the object. /// The type of the key. - /// the source observable of buffered changeset lists. + /// The source . /// An observable changeset combining all changes from each buffer into a single emission. /// is . public static IObservable> FlattenBufferResult(this IObservable>> source) @@ -1908,7 +1908,7 @@ public static IObservable> FlattenBufferResult /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The action to invoke for each change. Receives the full struct, including , , , and . /// A stream that forwards all changesets from unchanged. /// @@ -1938,9 +1938,9 @@ public static IObservable> ForEachChange - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, Optional, TDestination> resultSelector) @@ -1968,8 +1968,8 @@ public static IObservable> FullJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . @@ -1978,9 +1978,9 @@ public static IObservable> FullJoinLeft-side change handling: /// /// EventBehavior - /// AddEmits with the left value and the matching right (or Optional.None if no right exists). + /// AddEmits with the left value and the matching right (or if no right exists). /// UpdateRe-invokes with the new left value and current right (if any). - /// RemoveIf a right match still exists, re-invokes the selector with left as Optional.None. If neither side remains, removes the joined result. + /// RemoveIf a right match still exists, re-invokes the selector with left as . If neither side remains, removes the joined result. /// RefreshForwarded as Refresh on the joined result. /// /// @@ -1988,9 +1988,9 @@ public static IObservable> FullJoinRight-side change handling: /// /// EventBehavior - /// AddEmits with the matching left (or Optional.None) and the right value. + /// AddEmits with the matching left (or ) and the right value. /// UpdateRe-invokes selector with current left (if any) and the new right value. - /// RemoveIf a left match still exists, re-invokes the selector with right as Optional.None. If neither side remains, removes the joined result. + /// RemoveIf a left match still exists, re-invokes the selector with right as . If neither side remains, removes the joined result. /// RefreshForwarded as Refresh on the joined result. /// /// @@ -2017,9 +2017,9 @@ public static IObservable> FullJoin - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> FullJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) @@ -2048,8 +2048,8 @@ public static IObservable> FullJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2060,7 +2060,7 @@ public static IObservable> FullJoinManyEventBehavior /// AddEmits with the left value and the current right group for that key (may be empty). /// UpdateRe-invokes with the new left value and current right group. - /// RemoveIf the right group is non-empty, re-invokes with left as Optional.None. If both sides are empty, removes the result. + /// RemoveIf the right group is non-empty, re-invokes with left as . If both sides are empty, removes the result. /// RefreshForwarded as Refresh on the joined result. /// /// @@ -2103,9 +2103,9 @@ public static IObservable> FullJoinManyThe type of the object. /// The type of the key. /// The type of the group key. - /// the source changeset stream. - /// the group selector factory. - /// An of used to determine which groups appear in the result. + /// The source of . + /// The group selector factory. + /// An of used to determine which groups appear in the result. /// /// Useful for parent-child collection when the parent and child are soured from different streams. /// @@ -2129,7 +2129,7 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source of . /// A that extracts the group key from each item. /// An observable that emits group changesets. Each group exposes a sub-cache of its members. /// @@ -2167,9 +2167,9 @@ public static IObservable> Group - /// the source changeset stream. - /// A that extracts the group key from each item. - /// An that when this observable emits, all items are re-evaluated against the group selector, potentially moving items between groups. + /// The source of . + /// A that extracts the group key from each item. + /// An that, when it emits, all items are re-evaluated against the group selector, potentially moving items between groups. /// An observable that emits group changesets. /// This overload adds a signal. When it fires, every item in the cache is re-grouped using the current selector, which is useful when the grouping depends on mutable item state. public static IObservable> Group(this IObservable> source, Func groupSelectorKey, IObservable regrouper) @@ -2191,9 +2191,9 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// an observable that emits group selector functions. Each emission triggers a full re-grouping of all items. - /// An that optional signal to force re-evaluation of all items against the current selector. + /// The source of . + /// The that emits group selector functions. Each emission triggers a full re-grouping of all items. + /// An that optional signal to force re-evaluation of all items against the current selector. /// An observable that emits group changesets. /// /// @@ -2225,9 +2225,9 @@ public static IObservable> Group - /// the source changeset stream. - /// an observable of selector functions that take only the item (not the key). - /// An optional optional signal to force re-evaluation. + /// The source of . + /// The of selector functions that take only the item (not the key). + /// An optional signal to force re-evaluation. /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. public static IObservable> Group(this IObservable> source, IObservable> groupSelectorKeyObservable, IObservable? regrouper = null) where TObject : notnull @@ -2246,8 +2246,8 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . - /// A that factory that creates a group key observable for each item and its key. + /// The source of . + /// A factory that creates a group key observable for each item and its key. /// An observable that emits group changesets. Each group is a live sub-cache of its members. /// /// @@ -2303,8 +2303,8 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// the source changeset stream. - /// the group selector key. + /// The source of . + /// The group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) where TObject : notnull @@ -2323,9 +2323,9 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// the source changeset stream. - /// the property selector used to group the items. - /// A optional a time span that indicates the throttle to wait for property change events. + /// The source of . + /// The property selector used to group the items. + /// An optional a time span that indicates the throttle to wait for property change events. /// An optional the scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnProperty(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) @@ -2346,9 +2346,9 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// the source changeset stream. - /// the property selector used to group the items. - /// A optional a time span that indicates the throttle to wait for property change events. + /// The source of . + /// The property selector used to group the items. + /// An optional a time span that indicates the throttle to wait for property change events. /// An optional the scheduler. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnPropertyWithImmutableState(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) @@ -2369,9 +2369,9 @@ public static IObservable> Gr /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source of . /// A that extracts the group key from each item. - /// An that optional signal to force re-evaluation of all items against the group selector. + /// An that optional signal to force re-evaluation of all items against the group selector. /// An observable that emits immutable group changesets. /// /// @@ -2408,7 +2408,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// the source observable which emits change sets. + /// The source of . /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2420,8 +2420,8 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the ignore function (current,previous)=>{ return true to ignore }. + /// The source of . + /// The ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) where TObject : notnull @@ -2447,8 +2447,8 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the include function (current,previous)=>{ return true to include }. + /// The source of . + /// The include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) where TObject : notnull @@ -2466,10 +2466,10 @@ public static IObservable> IncludeUpdateWhen - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. - /// A that combines the left and right values into a destination object. The composite key is not provided in this overload. + /// The left of . + /// The right of . + /// A that maps each right item to the left key it should join on. + /// A that combines the left and right values into a destination object. The composite key is not provided in this overload. /// Overload that omits the composite key from the result selector. Delegates to . public static IObservable> InnerJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func resultSelector) where TLeft : notnull @@ -2495,8 +2495,8 @@ public static IObservable> IncludeUpdateWhenThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left of . + /// The right of . /// A that maps each right item to the left key it should join on. /// A that combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. @@ -2545,9 +2545,9 @@ public static IObservable> IncludeUpdateWhen - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> InnerJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2575,8 +2575,8 @@ public static IObservable> InnerJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2629,7 +2629,7 @@ public static IObservable> InnerJoinMany /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable that emits the same changesets as , unchanged. /// /// @@ -2647,9 +2647,9 @@ public static IObservable> InvokeEvaluate source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); /// - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the left value and the optional right into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2677,8 +2677,8 @@ public static IObservable> LeftJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . @@ -2687,7 +2687,7 @@ public static IObservable> LeftJoinLeft-side change handling: /// /// EventBehavior - /// AddAlways emits. Invokes with the left value and matching right (or Optional.None). + /// AddAlways emits. Invokes with the left value and matching right (or ). /// UpdateRe-invokes the selector with the new left value and current right (if any). /// RemoveRemoves the joined result. /// RefreshForwarded as Refresh on the joined result. @@ -2726,9 +2726,9 @@ public static IObservable> LeftJoin - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> LeftJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TDestination> resultSelector) @@ -2756,8 +2756,8 @@ public static IObservable> LeftJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2810,7 +2810,7 @@ public static IObservable> LeftJoinMany /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The maximum number of items allowed. Must be greater than zero. /// An observable changeset stream with size-limited contents. /// @@ -2846,9 +2846,9 @@ public static IObservable> LimitSizeTo( /// /// The type of the object. /// The type of the key. - /// the source cache to apply the size limit to. + /// The to operate on. /// The maximum number of items allowed. Must be greater than zero. - /// Optional scheduler for observing changes. Defaults to . + /// An optional for observing changes. Defaults to . /// An observable that emits batches of evicted key-value pairs whenever the cache exceeds the size limit. /// is . /// is zero or negative. @@ -2894,8 +2894,8 @@ public static IObservable>> LimitSizeTo< /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// the source cache changeset stream. - /// A that factory function that produces a child observable for each source item. + /// The source of . + /// A factory function that produces a child observable for each source item. /// An observable that emits values from all active child observables, interleaved by arrival order. /// /// @@ -2930,8 +2930,8 @@ public static IObservable MergeMany(t } /// - /// the source cache changeset stream. - /// A that factory function that receives both the item and its key, and returns a child observable. + /// The source of . + /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3007,7 +3007,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// An that emits changeset streams. Each inner stream is subscribed as it appears. - /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// A unified changeset stream containing changes from all active source streams. /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IComparer comparer) @@ -3028,7 +3028,7 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// An that emits changeset streams. Each inner stream is subscribed as it appears. - /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// A unified changeset stream containing changes from all active source streams. /// or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer) @@ -3048,8 +3048,8 @@ public static IObservable> MergeChangeSetsThe type of items in the changesets. /// The type of the key identifying items. /// An that emits changeset streams. Each inner stream is subscribed as it appears. - /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// A unified changeset stream containing changes from all active source streams. /// , , or is null. public static IObservable> MergeChangeSets(this IObservable>> source, IEqualityComparer equalityComparer, IComparer comparer) @@ -3069,8 +3069,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the first changeset stream. - /// the second changeset stream to merge with . + /// The source of . + /// The second changeset stream to merge with . /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3090,9 +3090,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the first changeset stream. - /// the second changeset stream to merge with . - /// An that comparer to determine which value wins when both sources provide the same key. + /// The source of . + /// The second changeset stream to merge with . + /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3113,9 +3113,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the first changeset stream. - /// the second changeset stream to merge with . - /// An that equality comparer to detect duplicate values for the same key. + /// The source of . + /// The second changeset stream to merge with . + /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3136,10 +3136,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the first changeset stream. - /// the second changeset stream to merge with . - /// An that equality comparer to detect duplicate values for the same key. - /// An that comparer to determine which value wins when both sources provide the same key. + /// The source of . + /// The second changeset stream to merge with . + /// An that equality comparer to detect duplicate values for the same key. + /// An that comparer to determine which value wins when both sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. @@ -3162,7 +3162,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the primary changeset stream. + /// The source of . /// An that additional changeset streams to merge with . /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. @@ -3183,9 +3183,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the primary changeset stream. + /// The source of . /// An that additional changeset streams to merge with . - /// An that comparer to determine which value wins when multiple sources provide the same key. + /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3206,9 +3206,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the primary changeset stream. + /// The source of . /// An that additional changeset streams to merge with . - /// An that equality comparer to detect duplicate values for the same key. + /// An that equality comparer to detect duplicate values for the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3229,10 +3229,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the primary changeset stream. + /// The source of . /// An that additional changeset streams to merge with . - /// An that equality comparer to detect duplicate values for the same key. - /// An that comparer to determine which value wins when multiple sources provide the same key. + /// An that equality comparer to detect duplicate values for the same key. + /// An that comparer to determine which value wins when multiple sources provide the same key. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. @@ -3255,7 +3255,7 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the collection of changeset streams to merge. + /// The source . /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3287,8 +3287,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the collection of changeset streams to merge. - /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// The source . + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3310,8 +3310,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the collection of changeset streams to merge. - /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// The source . + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3332,9 +3332,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// the collection of changeset streams to merge. - /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. + /// The source . + /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. + /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. /// An optional optional scheduler used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. @@ -3359,9 +3359,9 @@ public static IObservable> MergeChangeSetsThe type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// or is null. /// @@ -3384,9 +3384,9 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. - /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// , , or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer comparer) @@ -3410,10 +3410,10 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// An that optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// An that optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null, IComparer? comparer = null) @@ -3437,10 +3437,10 @@ public static IObservable> MergeManyCh /// The type of the key identifying parent items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of whose items each produce a child changeset stream. - /// A that factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. - /// An that optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. - /// An that optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. + /// The source of whose items each produce a child changeset stream. + /// A factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. + /// An that optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. + /// An that optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. /// A merged changeset stream containing all child items from all active parent subscriptions. /// /// @@ -3510,10 +3510,10 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// An that fallback comparer to resolve destination key conflicts when source items compare equal. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) @@ -3537,10 +3537,10 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. - /// An that fallback comparer to resolve destination key conflicts when source items compare equal. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IComparer childComparer) @@ -3557,11 +3557,11 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. - /// An that fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) @@ -3584,11 +3584,11 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. - /// An that fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IComparer childComparer) @@ -3606,11 +3606,11 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. - /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. - /// An that optional fallback comparer for destination key conflicts when source items compare equal. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3633,11 +3633,11 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. - /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. - /// An that optional fallback comparer for destination key conflicts when source items compare equal. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3654,12 +3654,12 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. + /// The source of . + /// A factory function that receives a source item and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. - /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. - /// An that optional fallback comparer for destination key conflicts when source items compare equal. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. + /// An that optional fallback comparer for destination key conflicts when source items compare equal. /// A merged changeset stream with conflicts resolved by source priority. /// or is null. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IComparer sourceComparer, bool resortOnSourceRefresh, IEqualityComparer? equalityComparer = null, IComparer? childComparer = null) @@ -3684,12 +3684,12 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child cache changeset stream. - /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child cache changeset stream. + /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// If (default), a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. - /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. - /// An that optional fallback comparer to resolve destination key conflicts when source items compare equal. + /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. + /// An that optional fallback comparer to resolve destination key conflicts when source items compare equal. /// A merged changeset stream containing items from all active child streams, with conflicts resolved by source priority. /// /// @@ -3723,9 +3723,9 @@ public static IObservable> MergeManyCh /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// the source cache changeset stream. - /// A that factory function that receives a source item and its key, and returns a child list changeset stream. - /// An that optional equality comparer to detect duplicate items in the merged list output. + /// The source of . + /// A factory function that receives a source item and its key, and returns a child list changeset stream. + /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull @@ -3745,9 +3745,9 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// the source cache changeset stream. - /// A that factory function that receives a source item and returns a child list changeset stream. - /// An that optional equality comparer to detect duplicate items in the merged list output. + /// The source of . + /// A factory function that receives a source item and returns a child list changeset stream. + /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. public static IObservable> MergeManyChangeSets(this IObservable> source, Func>> observableSelector, IEqualityComparer? equalityComparer = null) where TObject : notnull @@ -3766,8 +3766,8 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// the source cache changeset stream. - /// A that factory function that produces a child observable for each source item. + /// The source of . + /// A factory function that produces a child observable for each source item. /// An observable of pairing each emission with its source item. /// or is null. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) @@ -3781,8 +3781,8 @@ public static IObservable> MergeManyItems - /// the source cache changeset stream. - /// A that factory function that receives both the item and its key, and returns a child observable. + /// The source of . + /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull where TKey : notnull @@ -3799,7 +3799,7 @@ public static IObservable> MergeManyItems /// The type of the source observable. - /// the source observable to monitor. + /// The source to monitor for connection status. /// An observable that emits values reflecting the source's lifecycle. /// is . /// @@ -3810,7 +3810,7 @@ public static IObservable> MergeManyItems /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable that emits only non-empty changesets. /// is . /// @@ -3830,7 +3830,7 @@ public static IObservable> NotEmpty(thi /// The type of the objects in the source changeset. /// The type of the key. /// The destination type to filter and cast to. - /// the source observable changeset. + /// The source of . /// If , changesets that become empty after filtering are suppressed. /// An observable changeset of items. /// @@ -3860,8 +3860,8 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source of . - /// the callback invoked for each added item. Receives the new item and its key. + /// The source of . + /// The callback invoked for each added item. Receives the new item and its key. /// A stream that forwards all changesets from unchanged. /// /// @@ -3894,8 +3894,8 @@ public static IObservable> OnItemAdded( } /// - /// the source changeset stream. - /// the callback invoked for each added item. Receives only the item (no key). + /// The source of . + /// The callback invoked for each added item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemAdded(this IObservable> source, Action addAction) where TObject : notnull @@ -3907,8 +3907,8 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source of . - /// the callback invoked for each refreshed item. Receives the item and its key. + /// The source of . + /// The callback invoked for each refreshed item. Receives the item and its key. /// A stream that forwards all changesets from unchanged. /// /// @@ -3939,8 +3939,8 @@ public static IObservable> OnItemRefreshed - /// the source changeset stream. - /// the callback invoked for each refreshed item. Receives only the item (no key). + /// The source of . + /// The callback invoked for each refreshed item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) where TObject : notnull @@ -3953,8 +3953,8 @@ public static IObservable> OnItemRefreshed /// The type of the object. /// The type of the key. - /// The source of . - /// the callback invoked for each removed item. Receives the removed item and its key. + /// The source of . + /// The callback invoked for each removed item. Receives the removed item and its key. /// /// When (the default), the callback is also invoked for every item still in the cache /// when the subscription is disposed. When , only inline Remove changes trigger the callback. @@ -4003,8 +4003,8 @@ public static IObservable> OnItemRemoved - /// the source changeset stream. - /// the callback invoked for each removed item. Receives only the item (no key). + /// The source of . + /// The callback invoked for each removed item. Receives only the item (no key). /// When (the default), also invoked for all remaining items on disposal. /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRemoved(this IObservable> source, Action removeAction, bool invokeOnUnsubscribe = true) @@ -4018,8 +4018,8 @@ public static IObservable> OnItemRemoved /// The type of the object. /// The type of the key. - /// The source of . - /// the callback invoked for each updated item. Receives the current value, previous value, and key. + /// The source of . + /// The callback invoked for each updated item. Receives the current value, previous value, and key. /// A stream that forwards all changesets from unchanged. /// /// @@ -4050,8 +4050,8 @@ public static IObservable> OnItemUpdated - /// the source changeset stream. - /// the callback invoked for each updated item. Receives only the current and previous values (no key). + /// The source of . + /// The callback invoked for each updated item. Receives only the current and previous values (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) where TObject : notnull @@ -4063,7 +4063,7 @@ public static IObservable> OnItemUpdated /// The type of the object. /// The type of the key. - /// the first source changeset stream. + /// The source of . /// An that additional changeset streams to combine with. /// A changeset stream containing items present in any of the sources. /// @@ -4102,7 +4102,7 @@ public static IObservable> Or(this IObs } /// - /// a fixed collection of changeset streams to combine. + /// The of changeset streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Or(this ICollection>> sources) where TObject : notnull @@ -4119,7 +4119,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -4136,7 +4136,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4153,7 +4153,7 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits change sets. public static IObservable> Or(this IObservableList> sources) where TObject : notnull @@ -4169,8 +4169,8 @@ public static IObservable> Or(this IObs /// /// The type of the object. /// The type of the key. - /// the source cache to populate. - /// the observable that emits batches of items. + /// The to operate on. + /// The that emits batches of items. /// An that, when disposed, unsubscribes from . /// /// Each emission from is passed to , producing one changeset per emission containing Add or Update events for each item. Errors from propagate and terminate the subscription. Completion ends the subscription; the cache retains all items. @@ -4192,8 +4192,8 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// the source cache to populate. - /// the observable that emits individual items. + /// The to operate on. + /// The that emits individual items. /// An that, when disposed, unsubscribes from . /// or is . public static IDisposable PopulateFrom(this ISourceCache source, IObservable observable) @@ -4210,8 +4210,8 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// The source of . - /// the destination cache to populate. + /// The source of . + /// The that will receive the changes. /// An that, when disposed, unsubscribes from the source. /// /// @@ -4241,8 +4241,8 @@ public static IDisposable PopulateInto(this IObservable - /// the source changeset stream. - /// the destination intermediate cache to populate. + /// The source of . + /// The that will receive the changes. /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) where TObject : notnull @@ -4255,8 +4255,8 @@ public static IDisposable PopulateInto(this IObservable - /// the source changeset stream. - /// the destination lock-free cache to populate. + /// The source of . + /// The that will receive the changes. /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) where TObject : notnull @@ -4275,8 +4275,8 @@ public static IDisposable PopulateInto(this IObservableThe type of the object. /// The type of the key. /// The type of the destination. - /// the source changeset stream. - /// Projects the current snapshot to a result value. + /// The source of . + /// A function that projects the current snapshot to a result value. /// An observable that emits a projected value after each changeset. /// /// @@ -4309,7 +4309,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -4327,8 +4327,8 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// the source changeset stream. - /// A that should the query be triggered for observables on individual items. + /// The source of . + /// A that should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source, Func> itemChangedTrigger) @@ -4347,7 +4347,7 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// A ref-counted observable changeset stream. /// public static IObservable> RefCount(this IObservable> source) @@ -4364,7 +4364,7 @@ public static IObservable> RefCount(thi /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// The item to refresh. /// /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. @@ -4391,8 +4391,8 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// the source cache. - /// the items to refresh. + /// The to operate on. + /// The of items items to refresh. /// is . public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4408,7 +4408,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// is . public static void Refresh(this ISourceCache source) where TObject : notnull @@ -4424,7 +4424,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// The item to remove. /// /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. @@ -4452,7 +4452,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// The key of the item to remove. /// is . public static void Remove(this ISourceCache source, TKey key) @@ -4470,8 +4470,8 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// the source cache. - /// the items to remove. + /// The to operate on. + /// The of items items to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4488,8 +4488,8 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// the source cache. - /// the keys to remove. + /// The to operate on. + /// The keys to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable keys) where TObject : notnull @@ -4501,7 +4501,7 @@ public static void Remove(this ISourceCache source } /// - /// the intermediate cache. + /// The to operate on. /// The key of the item to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) @@ -4514,8 +4514,8 @@ public static void Remove(this IIntermediateCache } /// - /// the intermediate cache. - /// the keys to remove. + /// The to operate on. + /// The keys to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) where TObject : notnull @@ -4532,7 +4532,7 @@ public static void Remove(this IIntermediateCache /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// A list changeset stream without key information. /// /// @@ -4555,7 +4555,7 @@ public static IObservable> RemoveKey(this IOb /// /// The type of the object. /// The type of the key. - /// the source cache. + /// The to operate on. /// The key to remove. /// is . public static void RemoveKey(this ISourceCache source, TKey key) @@ -4572,8 +4572,8 @@ public static void RemoveKey(this ISourceCache sou /// /// The type of the object. /// The type of the key. - /// the source cache. - /// the keys to remove. + /// The to operate on. + /// The keys to remove. /// is . public static void RemoveKeys(this ISourceCache source, IEnumerable keys) where TObject : notnull @@ -4585,9 +4585,9 @@ public static void RemoveKeys(this ISourceCache so } /// - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoin(this IObservable> left, IObservable> right, Func rightKeySelector, Func, TRight, TDestination> resultSelector) @@ -4615,8 +4615,8 @@ public static IObservable> RightJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). /// An observable changeset keyed by . @@ -4625,7 +4625,7 @@ public static IObservable> RightJoinRight-side change handling: /// /// EventBehavior - /// AddAlways emits. Invokes with the matching left (or Optional.None) and the right value. + /// AddAlways emits. Invokes with the matching left (or ) and the right value. /// UpdateRe-invokes the selector with current left (if any) and the new right value. /// RemoveRemoves the joined result. /// RefreshForwarded as Refresh on the joined result. @@ -4664,9 +4664,9 @@ public static IObservable> RightJoin - /// the left changeset stream. - /// the right changeset stream. - /// A that maps each right item to the left key it should join on. + /// The left changeset stream. + /// The right changeset stream. + /// A that maps each right item to the left key it should join on. /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . public static IObservable> RightJoinMany(this IObservable> left, IObservable> right, Func rightKeySelector, Func, IGrouping, TDestination> resultSelector) @@ -4695,8 +4695,8 @@ public static IObservable> RightJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// of the left changeset stream. + /// of the right changeset stream. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -4749,7 +4749,7 @@ public static IObservable> RightJoinMany /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable that skips the first changeset and forwards all others. /// is . /// @@ -4768,8 +4768,8 @@ public static IObservable> SkipInitial( /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the comparer. + /// The source of . + /// The used to determine sort order. /// A that sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). /// An observable which emits change sets. @@ -4795,9 +4795,9 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the comparer observable. - /// the sort optimisations. + /// The source of . + /// The comparer observable. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4816,10 +4816,10 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the comparer observable. - /// An that signal to instruct the algorithm to re-sort the entire data set. - /// the sort optimisations. + /// The source of . + /// The comparer observable. + /// An that signals the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4838,10 +4838,10 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the comparer to sort on. - /// An that signal to instruct the algorithm to re-sort the entire data set. - /// the sort optimisations. + /// The source of . + /// The used to determine sort order. + /// An that signals the algorithm to re-sort the entire data set. + /// The sort optimisations. /// The reset threshold. /// An observable which emits change sets. [Obsolete(Constants.SortIsObsolete)] @@ -4862,9 +4862,9 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// A that expression that selects a comparable value from each item. - /// the sort direction. Defaults to ascending. + /// The source of . + /// A that expression that selects a comparable value from each item. + /// The sort direction. Defaults to ascending. /// A that sort optimization flags. /// The number of updates before the entire list is re-sorted (rather than inline sort). /// An observable that emits sorted changesets. @@ -4896,14 +4896,14 @@ public static IObservable> SortBy /// /// The type of the object. /// The type of the key. - /// the source observable change set. + /// The source of . /// An observable that emits an empty changeset first, then all source changesets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); /// - /// the source observable sorted change set. + /// The source of . /// An observable that emits an empty sorted changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4911,7 +4911,7 @@ public static IObservable> StartWithEmpty source.StartWith(SortedChangeSet.Empty); /// - /// the source observable virtual change set. + /// The source . /// An observable that emits an empty virtual changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4919,7 +4919,7 @@ public static IObservable> StartWithEmpty source.StartWith(VirtualChangeSet.Empty); /// - /// the source observable paged change set. + /// The source . /// An observable that emits an empty paged changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4930,7 +4930,7 @@ public static IObservable> StartWithEmptyThe type of the object. /// The type of the key. /// The grouping key type. - /// the source observable group change set. + /// The source . /// An observable that emits an empty group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4942,7 +4942,7 @@ public static IObservable> StartWithEm /// The type of the object. /// The type of the key. /// The grouping key type. - /// the source observable immutable group change set. + /// The source . /// An observable that emits an empty immutable group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4952,13 +4952,13 @@ public static IObservable> St /// /// The type of the item. - /// the source read only collection observable. + /// The source of . /// An observable that emits an empty collection first, then all source collections. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); /// - /// the source changeset stream. + /// The source of . /// The item to prepend. The key is extracted from . /// Overload for items that implement . Delegates to the explicit key overload. public static IObservable> StartWithItem(this IObservable> source, TObject item) @@ -4976,7 +4976,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The item to prepend. /// The key for the item. /// An observable that emits a single-item Add changeset first, then all source changesets. @@ -4997,8 +4997,8 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source of . - /// Factory that creates an for each item. Called on Add and Update (for the new value). + /// The source of . + /// A factory that creates an for each item. Called on Add and Update (for the new value). /// A stream that forwards all changesets from unchanged. /// /// @@ -5035,8 +5035,8 @@ public static IObservable> SubscribeMany - /// the source changeset stream. - /// Factory that creates an for each item. Receives the item and its key. + /// The source of . + /// A factory that creates an for each item. Receives the item and its key. /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) where TObject : notnull @@ -5053,7 +5053,7 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// the source observable change set. + /// The source of . /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull @@ -5077,7 +5077,7 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// an observable that emits inner changeset streams. + /// An of changeset streams. The operator subscribes to the latest inner stream. /// A changeset stream reflecting the items from the most recently emitted inner source. /// /// @@ -5106,7 +5106,7 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull @@ -5119,10 +5119,10 @@ public static IObservable> ToCollection /// The type of the object. /// The type of the key. - /// the source observable of individual items. - /// A that selects the unique key for each item. - /// A optional optional: per-item expiration time. Return for no expiration. - /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// The source . + /// A that selects the unique key for each item. + /// An optional optional: per-item expiration time. Return for no expiration. + /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional optional scheduler for expiration timing. /// An observable changeset stream. /// or is . @@ -5153,10 +5153,10 @@ public static IObservable> ToObservableChangeSet /// The type of the object. /// The type of the key. - /// the source observable of item batches. - /// A that selects the unique key for each item. - /// A optional optional: per-item expiration time. Return for no expiration. - /// Optional: maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. + /// The source . + /// A that selects the unique key for each item. + /// An optional optional: per-item expiration time. Return for no expiration. + /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional optional scheduler for expiration timing. /// An observable changeset stream. /// or is . @@ -5182,13 +5182,13 @@ public static IObservable> ToObservableChangeSet /// Watches a single key in the source changeset stream, emitting Optional.Some(value) when the key - /// is present and Optional.None when it is removed. Duplicate values are suppressed via . + /// is present and when it is removed. Duplicate values are suppressed via . /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source of . /// The key to watch. - /// An that optional comparer to suppress duplicate emissions. Uses default equality if . + /// An that optional comparer to suppress duplicate emissions. Uses default equality if . /// An observable of that reflects the presence or absence of the specified key. /// /// @@ -5199,7 +5199,7 @@ public static IObservable> ToObservableChangeSetEventBehavior /// AddEmits Optional.Some(value) if the key was not previously tracked. /// UpdateEmits Optional.Some(newValue) if the new value differs from the previous per . Otherwise suppressed. - /// RemoveEmits Optional.None. + /// RemoveEmits . /// RefreshEmits Optional.Some(value) if the value differs from the last emission per . Otherwise suppressed. /// OnErrorForwarded to the downstream observer. /// OnCompletedForwarded to the downstream observer. @@ -5223,10 +5223,10 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The key value. - /// Indicates if an initial Optional None should be emitted if the value doesn't exist. - /// Optional instance used to determine if an object value has changed. + /// When , emits an initial with no value if the key is not present in the cache. + /// An optional instance used to determine if an object value has changed. /// An observable optional. /// source is null. /// @@ -5256,9 +5256,9 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// the source changeset stream. - /// the sort function. - /// the sort order. Defaults to ascending. + /// The source of . + /// The sort function. + /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, Func sort, SortDirection sortOrder = SortDirection.Ascending) where TObject : notnull @@ -5270,8 +5270,8 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the sort comparer. + /// The source of . + /// The sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) where TObject : notnull @@ -5355,8 +5355,8 @@ public static IObservable> TransformThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . - /// a function that produces a from the current source item, the previous source item (if any), and the key. + /// The source of . + /// The tion that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. /// @@ -5473,8 +5473,8 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . - /// an async function that produces a from the current source item, the previous source item (if any), and the key. + /// The source of . + /// The async function that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. /// @@ -5560,8 +5560,8 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// the source changeset observable. - /// a pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. + /// The source of . + /// The pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. /// An observable changeset of transformed items. /// /// @@ -5603,9 +5603,9 @@ public static IObservable> TransformImmutableThe type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// the source changeset of parent items. + /// The source of . /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. - /// A that extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. + /// A that extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. /// An observable changeset of flattened child items. /// /// Change reason handling: @@ -5660,11 +5660,11 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// the source changeset of parent items. + /// The source of . /// An async function that expands a parent item (and its key) into an of children. - /// A that extracts a unique key from each child item. - /// An that optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. - /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. + /// A that extracts a unique key from each child item. + /// An that optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. + /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. The winning item is determined by this comparer. /// An observable changeset of flattened child items. /// /// @@ -5762,12 +5762,12 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// the source changeset of parent items. + /// The source of . /// An async function that expands a parent item (and its key) into an of children. - /// A that extracts a unique key from each child item. - /// A that called when throws. The faulting item is skipped and the stream continues. - /// An that optional comparer to determine if two child items with the same key are equal. - /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. + /// A that extracts a unique key from each child item. + /// A that called when throws. The faulting item is skipped and the stream continues. + /// An that optional comparer to determine if two child items with the same key are equal. + /// An that optional comparer to resolve key collisions when the same destination key is produced by multiple parents. /// An observable changeset of flattened child items. /// Because the transformations are asynchronous, each sub-collection may be emitted via a separate changeset. /// , , or is . @@ -5856,8 +5856,8 @@ public static IObservable> TransformMa /// The type of the source items. /// The type of the key. /// The type of the transformed items. - /// The source of . - /// A function that, given a source item and its key, returns an whose emissions become the transformed values. + /// The source of . + /// A function that, given a source item and its key, returns an whose emissions become the transformed values. /// An observable changeset where each key's value is the latest emission from its per-item observable. /// /// @@ -5950,10 +5950,10 @@ public static IObservable> TransformSafeThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// the source changeset observable. - /// a function that produces a from the current source item, the previous source item (if any), and the key. - /// Called when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. - /// An optional an observable that, when it emits a predicate, re-transforms all items for which the predicate returns . If , no forced re-transforms occur. + /// The source of . + /// The tion that produces a from the current source item, the previous source item (if any), and the key. + /// A callback invoked when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. + /// An optional that, when it emits a predicate, re-transforms all items for which the predicate returns . If , no forced re-transforms occur. /// An observable changeset of transformed items. /// /// @@ -6052,10 +6052,10 @@ public static IObservable> TransformSafeAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// the source changeset observable. - /// an async function that produces a . - /// A that called when throws or faults. The item is skipped and the stream continues. - /// An optional optional observable to force re-transformation of matching items. + /// The source of . + /// The async function that produces a . + /// A that called when throws or faults. The item is skipped and the stream continues. + /// An optional that forces re-transformation of matching items. /// An observable changeset of transformed items. /// Combines the async execution model of with the error-safe behavior of . /// , , or is . @@ -6123,9 +6123,9 @@ public static IObservable> TransformSafeAsync /// The type of the source items. Must be a reference type. /// The type of the key. - /// the source changeset of flat items. - /// a function that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. - /// An that optional observable that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. + /// The source of . + /// The tion that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. + /// An optional that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. /// An observable changeset of items representing the tree. /// /// Change reason handling: @@ -6199,10 +6199,10 @@ public static IObservable> TransformWithInlineUpd /// The type of the transformed items. Must be a reference type since items are mutated in place. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source of . /// A that called on Add (and optionally Refresh) to create a new . - /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. - /// A that called when or throws. The faulting item is skipped. + /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. + /// A that called when or throws. The faulting item is skipped. /// When , Refresh changes call on the existing item. /// An observable changeset of transformed items. /// @@ -6238,7 +6238,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -6273,9 +6273,9 @@ static IEnumerable> ReplaceMoves(IChangeSet /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// the source changeset stream. - /// A that factory that produces a condition observable for each item. - /// A that predicate applied to each per-item observable's latest value. + /// The source of . + /// A factory that produces a condition observable for each item. + /// A that predicate applied to each per-item observable's latest value. /// An observable of bool that emits whenever the all-items condition changes. /// , , or is . /// @@ -6309,9 +6309,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// the source changeset stream. - /// A that selector which returns the target observable. - /// the equality condition. + /// The source of . + /// A that selector which returns the target observable. + /// The equality condition. /// An observable which boolean values indicating if true. /// source. public static IObservable TrueForAll(this IObservable> source, Func> observableSelector, Func equalityCondition) @@ -6326,9 +6326,9 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// the source changeset stream. - /// A that factory that produces a condition observable for each item. - /// A that predicate applied to each item and its per-item observable's latest value. + /// The source of . + /// A factory that produces a condition observable for each item. + /// A that predicate applied to each item and its per-item observable's latest value. /// An observable of bool that emits whenever the any-item condition changes. /// , , or is . /// @@ -6350,9 +6350,9 @@ public static IObservable TrueForAny(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// the source changeset stream. - /// A that factory that produces a condition observable for each item. - /// A that predicate applied to each per-item observable's latest value (without the item). + /// The source of . + /// A factory that produces a condition observable for each item. + /// A that predicate applied to each per-item observable's latest value (without the item). /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. public static IObservable TrueForAny(this IObservable> source, Func> observableSelector, Func equalityCondition) where TObject : notnull @@ -6372,7 +6372,7 @@ public static IObservable TrueForAny(this IObservab /// /// The type of the object. /// The type of the key. - /// the source sorted changeset stream. + /// The source of . /// An observable that emits the sorted changesets after updating item indices. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware @@ -6384,7 +6384,7 @@ public static IObservable> UpdateIndex /// The type of the object. /// The type of the key. - /// the source changeset stream. + /// The source of . /// The key to observe. /// An observable of for the specified key only. /// @@ -6418,7 +6418,7 @@ public static IObservable> Watch(this IObse /// /// /// Unlike , - /// this does not emit Optional.None on removal. It emits the removed item's value instead. + /// this does not emit on removal. It emits the removed item's value instead. /// If you need to distinguish presence from absence, use ToObservableOptional. /// /// @@ -6444,7 +6444,7 @@ public static IObservable WatchValue(this IObservableCac } /// - /// the source changeset stream. + /// The source of . /// The key to observe. /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) @@ -6462,8 +6462,8 @@ public static IObservable WatchValue(this IObservable /// The type of the object (must implement ). /// The type of the key. - /// The source of . - /// Specific property names to monitor. If empty, all property changes trigger emissions. + /// The source of . + /// The specific property names to monitor. If empty, all property changes trigger emissions. /// An observable that emits the item itself each time a monitored property changes. /// /// @@ -6502,8 +6502,8 @@ public static IObservable WatchValue(this IObservableThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source of . - /// A that expression selecting the property to monitor. + /// The source of . + /// A that expression selecting the property to monitor. /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of containing both the item and its property value. /// @@ -6540,7 +6540,7 @@ public static IObservable> WhenPropertyChangedThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source of . + /// The source of . /// A that expression selecting the property to monitor. /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of property values. The owning item is not included; use if you need it. @@ -6579,8 +6579,8 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the reasons. + /// The source of . + /// The values to filter by. /// An observable which emits a change set with items matching the reasons. /// reasons. /// Must select at least on reason. @@ -6609,8 +6609,8 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// the source changeset stream. - /// the reasons. + /// The source of . + /// The values to filter by. /// An observable which emits a change set with items not matching the reasons. /// reasons. /// Must select at least on reason. @@ -6639,7 +6639,7 @@ public static IObservable> WhereReasonsAreNot /// The type of the object. /// The type of the key. - /// the first source changeset stream. + /// The source of . /// An that additional changeset streams to combine with. /// A changeset stream containing items present in exactly one source. /// @@ -6678,7 +6678,7 @@ public static IObservable> Xor(this IOb } /// - /// a fixed collection of changeset streams to combine. + /// The of changeset streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Xor(this ICollection>> sources) where TObject : notnull @@ -6695,7 +6695,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull @@ -6712,7 +6712,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull @@ -6729,7 +6729,7 @@ public static IObservable> Xor(this IOb /// /// The type of the object. /// The type of the key. - /// the source collection of changeset streams. + /// The of changeset streams to combine. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList> sources) where TObject : notnull From a9e021d48cfe9d2d0742b27c68588185aaafe5d9 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 13:16:40 -0700 Subject: [PATCH 19/23] Perfect param descriptions: purpose verbs, combined crefs, no redundancy - Add operator-specific purpose verbs to 150+ source params (to filter, to sort, to join, etc.) - Fix mutation helper params with specific purposes (to add or update items in, to clear, etc.) - Combine all split IObservable{T}/IChangeSet crefs into single nested format - Remove 'changeset stream' redundancy after IChangeSet type references - Remove type name echoes (comparer after IComparer, scheduler after IScheduler) - Fix broken 'tion' fragments, doubled 'items items', grammar issues - Add type links to SortAndBind and VirtualiseAndPage source params - Update documentation skill with comprehensive param writing guidance and examples --- .github/skills/add-documentation/SKILL.md | 77 ++- .../Cache/ObservableCacheEx.SortAndBind.cs | 20 +- .../ObservableCacheEx.VirtualiseAndPage.cs | 16 +- src/DynamicData/Cache/ObservableCacheEx.cs | 536 +++++++++--------- 4 files changed, 345 insertions(+), 304 deletions(-) diff --git a/.github/skills/add-documentation/SKILL.md b/.github/skills/add-documentation/SKILL.md index f7db50b31..69ac28012 100644 --- a/.github/skills/add-documentation/SKILL.md +++ b/.github/skills/add-documentation/SKILL.md @@ -31,8 +31,8 @@ Start from this template for any primary overload. Delete sections that do not a /// /// The type of items. /// The type of the key. -/// The source of . -/// An that [what it controls]. +/// The source to [verb: filter, transform, sort, etc.]. +/// An that determines sort order. /// [What it emits and what each emission represents.] /// Thrown when is null. /// @@ -129,26 +129,67 @@ Refresh behavior varies significantly between operators: some re-evaluate (Filte **Params**: Every `` must read as natural English with the type linked via `` woven into the sentence. No type is exempt from linking (including enums, `Optional`, `Change`, `IChangeSet`, standard library types like `IComparer`, `TimeSpan`, `IScheduler`). Use `` / `` / `` for C# keywords. Param writing rules: -- Start with an article ("The", "A", "An") or a condition ("When", "If") -- The type link appears naturally in the sentence, not as a prefix dumped before the description -- Never echo the parameter name as the entire description ("The source.", "The destination.") -- For `IObservable>` source params, use the two-part format: `The source of .` -- For deeply nested generics (3+ levels), use `{T}` in the cref and describe the actual type in prose -- For `params` array parameters, do not include `[]` in the cref. Mention "array" in prose if needed. -- For `Optional.None` references, use `` +- **Reads as English.** Read it aloud. If it sounds wrong, it IS wrong. +- **Starts with an article** ("The", "A", "An") or a condition ("When", "If"). +- **Links the actual parameter type** from the method signature. Use ``. Get the generic type arguments right (e.g., `IComparer{TObject}` not `IComparer{T}` when the param type is `IComparer`). +- **Describes the purpose**, not just the type. Every param description must answer: "what does the caller use this for?" +- **No redundancy with the type name.** The type `IChangeSet` already says "changeset", so don't add "changeset stream" after it. The type `IObservable` already says "observable", so don't add "observable" after it. The type `IComparer` already says "comparer", so don't add "comparer" after it. +- **No double articles.** "The source [type] the left stream" has two articles fighting each other. +- **Combined nested crefs** for observable changeset types. Write `IObservable{IChangeSet{TObject, TKey}}` as one cref. NEVER split into `IObservable{T}` + "of" + `IChangeSet{...}`. +- **For deeply nested generics** (3+ nesting levels), use `{T}` in the cref and describe the actual type in prose. +- **For `params` array parameters**, do not include `[]` in the cref. +- **For `Optional.None`**, use ``. ```xml - -/// the source. -/// the destination. -/// A that The binding options. + - + /// The source of . + + +/// The source changeset stream. + + +/// The . + + +/// The comparer used for sorting. + + +/// The source the left input. + + + + +/// The source to filter. +/// The source to transform. +/// The source to bind. +/// The to add items to. + + +/// The left to join. +/// The right to join. + + /// The that will receive the changes. -/// The that controls binding behavior. -/// An optional for scheduling work. -/// The used to determine whether a new item is the same as an existing cached item. +/// The output that will be populated with the results. + + +/// The that determines sort order. +/// An optional for determining item equality. + + +/// A that projects each source item into a destination item. +/// A predicate that determines which items to include. +/// A that extracts the join key from each right item. + + +/// An optional for scheduling expiry timers. +/// The that controls reset threshold and binding behavior. + + +/// When , re-invokes the transform factory on Refresh changes instead of forwarding them. +/// When , invokes the callback for all tracked items when the subscription is disposed. ``` **SeeAlso**: Bidirectional for overload sets. Link safe/async/immutable variants, similar operators, complementary operators, commonly confused operators. @@ -225,4 +266,4 @@ dotnet build src/DynamicData/DynamicData.csproj --no-restore -c Release --framew | Multiple agents editing same file | One editor at a time | | Removing existing information | Additive only; diff against main | | Only cache rows for list operators | List needs AddRange, RemoveRange, Moved, Clear | -| Params missing type links | Every param links its type | \ No newline at end of file +| Params missing type links | Every param links its type | diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index b92009853..20ce2016a 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -18,7 +18,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// An observable which will emit change sets. /// Creates a and delegates to . @@ -39,7 +39,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// The with default settings. /// An observable which will emit change sets. @@ -62,7 +62,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The list to bind to. /// An observable which will emit change sets. /// This is the primary Bind overload for paged data. It applies paged changeset mutations directly to the target list. @@ -78,7 +78,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The list to bind to. /// The with default settings. /// An observable which will emit change sets. @@ -96,7 +96,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// An observable which will emit change sets. /// Creates a and delegates to . @@ -117,7 +117,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// The with default settings. /// An observable which will emit change sets. @@ -140,7 +140,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The list to bind to. /// An observable which will emit change sets. /// This is the primary Bind overload for virtualized data. It applies virtualized changeset mutations directly to the target list. @@ -156,7 +156,7 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to sort and bind. /// The list to bind to. /// The with default settings. /// An observable which will emit change sets. @@ -310,7 +310,7 @@ public static partial class ObservableCacheEx source.SortAndBind(out readOnlyObservableCollection, comparer, DynamicDataOptions.SortAndBind); /// - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// The comparer to order the resulting dataset. /// The controlling reset threshold and initial capacity. @@ -342,7 +342,7 @@ public static partial class ObservableCacheEx source.SortAndBind(out readOnlyObservableCollection, comparerChanged, DynamicDataOptions.SortAndBind); /// - /// The source changeset stream. + /// The source to sort and bind. /// The resulting read only observable collection. /// An observable of comparers which enables the sort order to be changed. /// The controlling reset threshold and initial capacity. diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index f02aa8004..4316e0d95 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -42,7 +42,7 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to paginate. /// The comparer to order the resulting dataset. /// The virtualizing requests (start index and page size). /// The for controlling virtualization behavior. @@ -86,7 +86,7 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to paginate. /// An observable of comparers which enables the sort order to be changed. /// The virtualizing requests (start index and page size). /// The for controlling virtualization behavior. @@ -129,7 +129,7 @@ public static IObservable>> So /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to paginate. /// The virtualising requests. /// An observable which will emit virtual change sets. /// source. @@ -150,7 +150,7 @@ public static IObservable> Virtualise /// The type of the object. /// The type of the key. - /// The source of . + /// The source to limit. /// The used to determine sort order. /// The maximum number of items to return. /// An observable which will emit virtual change sets. @@ -184,7 +184,7 @@ public static IObservable>> To /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to paginate. /// The size. /// An observable which will emit virtual change sets. /// source. @@ -234,7 +234,7 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to paginate. /// The comparer to order the resulting dataset. /// The page requests (page number and page size). /// The for controlling paging behavior. @@ -277,7 +277,7 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source changeset stream. + /// The source to paginate. /// An observable of comparers which enables the sort order to be changed. /// The page requests (page number and page size). /// The for controlling paging behavior. @@ -319,7 +319,7 @@ public static IObservable>> SortA /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to paginate. /// The page requests. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index e50f47acf..680e0b060 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -33,7 +33,7 @@ public static partial class ObservableCacheEx /// /// The type of items in the cache. /// The type of the key. - /// The source of . + /// The source to observe and adapt. /// The whose Adapt method is called for each changeset. /// An observable that emits the same changesets as , after the adaptor has processed each one. /// @@ -65,7 +65,7 @@ public static IObservable> Adapt(this I } /// - /// The source of . + /// The source to observe and adapt. /// The whose Adapt method is called for each changeset. /// This overload operates on . Delegates to Rx's Do operator. public static IObservable> Adapt(this IObservable> source, ISortedChangeSetAdaptor adaptor) @@ -84,7 +84,7 @@ public static IObservable> Adapt(this I /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to add or update items in. /// The item to add or update. /// /// Convenience method that wraps a single-item mutation inside . @@ -111,9 +111,9 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The to operate on. + /// The to add or update items in. /// The item to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// The used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// This overload uses to suppress no-op updates when the new value equals the existing one. public static void AddOrUpdate(this ISourceCache source, TObject item, IEqualityComparer equalityComparer) where TObject : notnull @@ -125,8 +125,8 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The to operate on. - /// The of items items to add or update. + /// The to add or update items in. + /// The of items to add or update. /// Batch overload. All items are added/updated inside a single call, producing one changeset. public static void AddOrUpdate(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -138,9 +138,9 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The to operate on. - /// The of items items to add or update. - /// The equality comparer used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. + /// The to add or update items in. + /// The of items to add or update. + /// The used to determine whether a new item is the same as an existing cached item. When equal, the update is skipped. /// Batch overload with equality comparison. All items are added/updated inside a single call. public static void AddOrUpdate(this ISourceCache source, IEnumerable items, IEqualityComparer equalityComparer) where TObject : notnull @@ -152,7 +152,7 @@ public static void AddOrUpdate(this ISourceCache s } /// - /// The to operate on. + /// The to add or update items in. /// The item to add or update. /// The key to associate with the item. /// This overload operates on , which requires an explicit key parameter. @@ -172,8 +172,8 @@ public static void AddOrUpdate(this IIntermediateCache /// The type of the object. /// The type of the key. - /// The source of . - /// The other array of changeset streams to combine with. + /// The source to combine. + /// The additional streams to combine with. /// An observable which emits change sets. /// source or others. /// @@ -193,7 +193,7 @@ public static IObservable> And(this IOb /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits change sets. /// /// source @@ -215,7 +215,7 @@ public static IObservable> And(this ICo /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits change sets. public static IObservable> And(this IObservableList>> sources) where TObject : notnull @@ -284,7 +284,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to materialize into a read-only cache. /// If (default), all cache operations are synchronized. Set to when the caller guarantees single-threaded access. /// A read-only observable cache that reflects the current state of the pipeline. /// @@ -324,7 +324,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of items in the cache. /// The type of the key. - /// The source of . + /// The source to process. /// /// /// Invoked once per subscription, providing an that signals when all @@ -371,10 +371,10 @@ public static IObservable> AsyncDisposeMany /// The object of the change set. /// The key of the change set. - /// The source of . + /// The source to monitor for property-driven refresh signals. /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements have successive property changes. /// An optional throttle applied to each item's property change notifications, preventing excessive refresh invocations. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable change set with additional refresh changes. /// public static IObservable> AutoRefresh(this IObservable> source, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) @@ -403,11 +403,11 @@ public static IObservable> AutoRefresh( /// The object of the change set. /// The key of the change set. /// The type of the property. - /// The source of . + /// The source to monitor for property-driven refresh signals. /// A that specify a property to observe changes. When it changes a Refresh is invoked. /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements have successive property changes. /// An optional throttle applied to each item's property change notifications, preventing excessive refresh invocations. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable change set with additional refresh changes. public static IObservable> AutoRefresh(this IObservable> source, Expression> propertyAccessor, TimeSpan? changeSetBuffer = null, TimeSpan? propertyChangeThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -435,10 +435,10 @@ public static IObservable> AutoRefreshThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source of . + /// The source to monitor for observable-driven refresh signals. /// The observable which acts on items within the collection and produces a value when the item should be refreshed. /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements require a refresh. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable change set with additional refresh changes. /// public static IObservable> AutoRefreshOnObservable(this IObservable> source, Func> reevaluator, TimeSpan? changeSetBuffer = null, IScheduler? scheduler = null) @@ -451,10 +451,10 @@ public static IObservable> AutoRefreshOnObservableThe object of the change set. /// The key of the change set. /// The type of evaluation. - /// The source of . + /// The source to monitor for observable-driven refresh signals. /// The observable which acts on items within the collection and produces a value when the item should be refreshed. /// An optional buffer duration. Batches multiple refresh signals into a single changeset, improving performance when many elements change in quick succession. This greatly increases performance when many elements require a refresh. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable change set with additional refresh changes. /// /// Worth noting: Per-item observable errors are silently ignored (not forwarded to the downstream observer). Only source stream errors propagate. @@ -475,7 +475,7 @@ public static IObservable> AutoRefreshOnObservable /// The type of the object. /// The type of the key. - /// The source of . + /// The source to batch. /// The time window for batching. /// The scheduler for timing. Defaults to . /// An observable that emits merged changesets, one per time window. @@ -531,7 +531,7 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to conditionally buffer. /// An that when , buffering begins. When , the buffer is flushed. /// If , starts in a paused (buffering) state. /// A that maximum time the buffer stays open. When elapsed, the buffer is flushed regardless of pause state. @@ -567,7 +567,7 @@ public static IObservable> BatchIf(this } /// - /// The source of . + /// The source to conditionally buffer. /// An that controls buffering: begins buffering, flushes the buffer. /// If , starts in a paused (buffering) state. /// An optional timer. The buffer is flushed each time the timer produces a value, and buffering ceases when it completes. @@ -582,7 +582,7 @@ public static IObservable> BatchIf(this /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The number of changes before a reset notification is triggered. /// An observable which will emit change sets. @@ -610,7 +610,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The that controls binding behavior. /// An observable which will emit change sets. @@ -629,7 +629,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The that applies changes to the bound collection. /// An observable which will emit change sets. @@ -660,7 +660,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The output that will be populated with the results. /// The that controls binding behavior. /// An observable which will emit change sets. @@ -681,7 +681,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The output that will be populated with the results. /// The number of changes before a reset notification is triggered. /// When , uses Replace instead of Remove/Add for updates in the bound collection. Not all platforms support replace notifications. @@ -717,7 +717,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// An observable which will emit change sets. /// source. @@ -736,7 +736,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The that controls binding behavior. /// An observable which will emit change sets. @@ -757,7 +757,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The that applies changes to the bound collection. /// An observable which will emit change sets. @@ -788,7 +788,7 @@ public static IObservable> Bind(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The output that will be populated with the results. /// The that controls binding behavior. /// An observable which will emit change sets. @@ -811,7 +811,7 @@ public static IObservable> Bind(this IO /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to bind to a collection. /// The output that will be populated with the results. /// The number of changes before a reset event is called on the observable collection. /// When , uses Replace instead of Remove/Add for updates in the bound collection. Not all platforms support replace notifications. @@ -845,7 +845,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The reset threshold. /// An observable which will emit change sets. @@ -869,7 +869,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The key type. - /// The source of . + /// The source to bind to a collection. /// The that will receive the changes. /// The reset threshold. /// An observable which will emit change sets. @@ -896,7 +896,7 @@ public static IObservable> Bind(this IO /// /// The object type. /// The type of the key. - /// The source of . + /// The source to buffer during the initial loading period. /// The time window to buffer, measured from when the first changeset arrives. /// The scheduler for timing. Defaults to . /// An observable that emits one merged changeset for the initial burst, then passthrough for the rest. @@ -927,7 +927,7 @@ public static IObservable> BufferInitialThe type of the source object. /// The type of the key. /// The type of the destination object. - /// The source of . + /// The source to cast. /// The conversion function applied to each item. /// An observable changeset of converted items. /// @@ -959,8 +959,8 @@ public static IObservable> CastThe type of the object. /// The type of the source key. /// The type of the destination key. - /// The source of . - /// The tion that computes the destination key from the item, e.g. (item) => item.NewId. + /// The source to re-key. + /// The that computes the destination key from the item, e.g. (item) => item.NewId. /// An observable changeset with items re-keyed using . /// /// @@ -1016,7 +1016,7 @@ public static IObservable> ChangeKey /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to clear. /// /// /// EventBehavior @@ -1063,7 +1063,7 @@ public static void Clear(this LockFreeObservableCache /// The type of the object. /// The type of the key. - /// The source of . + /// The source to clone. /// The target collection to which changes are applied. /// An observable that forwards all changesets from unchanged. /// @@ -1120,7 +1120,7 @@ public static IObservable> Clone(this I /// The type of the object. /// The type of the key. /// The type of the destination. - /// The source of . + /// The source to convert. /// The conversion factory. /// An observable which emits change sets. [Obsolete("This was an experiment that did not work. Use Transform instead")] @@ -1146,7 +1146,7 @@ public static IObservable> Convert /// The type of the object. /// The type of the key. - /// The source of . + /// The source to defer until the first changeset arrives. /// An observable that begins emitting changesets once the first non-empty changeset is received. /// /// @@ -1192,7 +1192,7 @@ public static IObservable> DeferUntilLoaded /// The type of the object. /// The type of the key. - /// The source of . + /// The source to track for disposal on removal. /// A stream that forwards all changesets from unchanged. /// /// @@ -1230,7 +1230,7 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source of . + /// The source to extract distinct values from. /// The value selector. /// An observable which will emit distinct change sets. /// @@ -1251,8 +1251,8 @@ public static IObservable> DistinctValues - /// The to operate on. - /// The complete snapshot of items to diff against the cache. + /// The to diff and update. + /// The representing the complete desired state to diff against the cache. /// An used to determine whether a new item is the same as an existing cached item. /// /// This overload uses an instead of a delegate @@ -1275,9 +1275,9 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// The to operate on. - /// The complete snapshot of desired items. - /// The tion that returns when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. + /// The to diff and update. + /// The representing the complete desired state. + /// The that returns when the current and previous items are considered equal, e.g. (current, previous) => current.Version == previous.Version. /// /// /// EventBehavior @@ -1309,8 +1309,8 @@ public static void EditDiff(this ISourceCache sour /// /// The type of the object. /// The type of the key. - /// The source . - /// The tion to extract the unique key from each item. + /// The source to convert into a keyed changeset stream. + /// The that extracts the unique key from each item. /// An optional for comparing items. Uses default equality if . /// An observable changeset representing the incremental differences between successive snapshots. /// @@ -1342,8 +1342,8 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// The source . - /// The tion to extract the unique key from each item. + /// The source to convert into a keyed changeset stream. + /// The that extracts the unique key from each item. /// An optional for comparing items. Uses default equality if . /// An observable changeset tracking the single optional item. /// @@ -1374,7 +1374,7 @@ public static IObservable> EditDiff(thi /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to validate for unique keys. /// A changeset stream guaranteed to contain unique keys per changeset. /// /// @@ -1402,8 +1402,8 @@ public static IObservable> EnsureUniqueKeys /// The type of the object. /// The type of the key. - /// The source of . - /// The other array of changeset streams to combine with. + /// The source to combine. + /// The additional streams to combine with. /// An observable which emits change sets. /// /// source @@ -1431,7 +1431,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits change sets. /// /// source @@ -1453,7 +1453,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits change sets. public static IObservable> Except(this IObservableList>> sources) where TObject : notnull @@ -1504,7 +1504,7 @@ public static IObservable> Except(this /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to apply time-based expiration to. /// An optional a function returning the expiration timeout for each item, or for no expiration. /// An observable changeset that includes timer-driven Remove changes for expired items. /// @@ -1531,7 +1531,7 @@ public static IObservable> ExpireAfter( timeSelector: timeSelector); /// - /// The source of . + /// The source to apply time-based expiration to. /// An optional a function returning the expiration timeout for each item, or for no expiration. /// The used to schedule expiration timers. public static IObservable> ExpireAfter( @@ -1546,7 +1546,7 @@ public static IObservable> ExpireAfter( scheduler: scheduler); /// - /// The source of . + /// The source to apply time-based expiration to. /// An optional a function returning the expiration timeout for each item, or for no expiration. /// An optional polling interval. If specified, items are expired on a polling interval rather than per-item timers. Less accurate but more efficient when many items share similar expiration times. /// @@ -1565,7 +1565,7 @@ public static IObservable> ExpireAfter( pollingInterval: pollingInterval); /// - /// The source of . + /// The source to apply time-based expiration to. /// An optional a function returning the expiration timeout for each item, or for no expiration. /// An optional if specified, items are expired on a polling interval rather than per-item timers. /// The used to schedule polling and expiration timers. @@ -1618,7 +1618,7 @@ public static IObservable>> ExpireAfter< /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to filter. /// The predicate used to determine whether each item is included. /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets, which can be useful for monitoring loading status. /// An observable changeset containing only items that satisfy . @@ -1671,7 +1671,7 @@ public static IObservable> Filter( /// The type of the object. /// The type of the key. /// The type of state value required by . - /// The source of . + /// The source to filter. /// The stream of state values to be passed to . /// The predicate that receives the current state and an item, returning to include or to exclude. /// When (default), empty changesets are suppressed for performance. Set to to emit empty changesets. @@ -1709,7 +1709,7 @@ public static IObservable> Filter - /// The source of . + /// The source to filter. /// The that emits new predicates. Each emission replaces the current predicate and triggers a full re-evaluation of all items. /// The that, when it emits, triggers a full re-evaluation of all items against the current predicate. Useful when filtering on mutable item properties. /// When (default), empty changesets are suppressed for performance. @@ -1739,7 +1739,7 @@ public static IObservable> Filter( /// /// The type of collection items to be filtered. /// The type of the key values of each collection item. - /// The source of . + /// The source to filter (items assumed immutable). /// The filtering predicate to be applied to each item. /// A flag indicating whether the created stream should emit empty changesets. Empty changesets are suppressed by default, for performance. Set to ensure that a downstream changeset occurs for every upstream changeset. /// A stream of collection changesets where upstream collection items are filtered by the given predicate. @@ -1787,7 +1787,7 @@ public static IObservable> FilterImmutable /// The type of the object. /// The type of the key. - /// The source of . + /// The source to process. /// A factory that creates an for each item and its key. When the observable emits , the item is included; when , it is excluded. /// A that optional time window to buffer inclusion changes from per-item observables before re-evaluating. /// An that optional scheduler used for buffering. @@ -1853,7 +1853,7 @@ public static IObservable> FilterOnObservableFinally operator instead. /// /// The type contained within the observables. - /// The source . + /// The source to attach a finally action to. /// The finally action. /// An observable which has always a finally action applied. [Obsolete("This can cause unhandled exception issues so do not use")] @@ -1871,7 +1871,7 @@ public static IObservable FinallySafe(this IObservable source, Action f /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to flatten into individual changes. /// An observable of individual values. /// is . /// @@ -1890,7 +1890,7 @@ public static IObservable> Flatten(this IOb /// /// The type of the object. /// The type of the key. - /// The source . + /// The source to flatten. /// An observable changeset combining all changes from each buffer into a single emission. /// is . public static IObservable> FlattenBufferResult(this IObservable>> source) @@ -1908,7 +1908,7 @@ public static IObservable> FlattenBufferResult /// The type of the object. /// The type of the key. - /// The source of . + /// The source to observe each individual change in. /// The action to invoke for each change. Receives the full struct, including , , , and . /// A stream that forwards all changesets from unchanged. /// @@ -1938,8 +1938,8 @@ public static IObservable> ForEachChange - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -1968,8 +1968,8 @@ public static IObservable> FullJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . @@ -2017,8 +2017,8 @@ public static IObservable> FullJoin - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -2048,8 +2048,8 @@ public static IObservable> FullJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left value, and the right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2103,7 +2103,7 @@ public static IObservable> FullJoinManyThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group. /// The group selector factory. /// An of used to determine which groups appear in the result. /// @@ -2129,7 +2129,7 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group. /// A that extracts the group key from each item. /// An observable that emits group changesets. Each group exposes a sub-cache of its members. /// @@ -2167,7 +2167,7 @@ public static IObservable> Group - /// The source of . + /// The source to group. /// A that extracts the group key from each item. /// An that, when it emits, all items are re-evaluated against the group selector, potentially moving items between groups. /// An observable that emits group changesets. @@ -2191,7 +2191,7 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group. /// The that emits group selector functions. Each emission triggers a full re-grouping of all items. /// An that optional signal to force re-evaluation of all items against the current selector. /// An observable that emits group changesets. @@ -2225,7 +2225,7 @@ public static IObservable> Group - /// The source of . + /// The source to group. /// The of selector functions that take only the item (not the key). /// An optional signal to force re-evaluation. /// This overload accepts a selector that does not receive the key. Delegates to the overload accepting Func<TObject, TKey, TGroupKey>. @@ -2246,7 +2246,7 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to process. /// A factory that creates a group key observable for each item and its key. /// An observable that emits group changesets. Each group is a live sub-cache of its members. /// @@ -2303,7 +2303,7 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group using per-item observables. /// The group selector key. /// An observable which will emit group change sets. public static IObservable> GroupOnObservable(this IObservable> source, Func> groupObservableSelector) @@ -2323,10 +2323,10 @@ public static IObservable> GroupOnObse /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group by a property value. /// The property selector used to group the items. /// An optional a time span that indicates the throttle to wait for property change events. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnProperty(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2346,10 +2346,10 @@ public static IObservable> GroupOnProp /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group by a property value with immutable snapshots. /// The property selector used to group the items. /// An optional a time span that indicates the throttle to wait for property change events. - /// An optional the scheduler. + /// An optional for scheduling work. /// An observable which will emit immutable group change sets. public static IObservable> GroupOnPropertyWithImmutableState(this IObservable> source, Expression> propertySelector, TimeSpan? propertyChangedThrottle = null, IScheduler? scheduler = null) where TObject : INotifyPropertyChanged @@ -2369,7 +2369,7 @@ public static IObservable> Gr /// The type of the object. /// The type of the key. /// The type of the group key. - /// The source of . + /// The source to group with immutable snapshots. /// A that extracts the group key from each item. /// An that optional signal to force re-evaluation of all items against the group selector. /// An observable that emits immutable group changesets. @@ -2408,7 +2408,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// The source of . + /// The source to filter same-reference updates from. /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2420,7 +2420,7 @@ public static IObservable> IgnoreSameReferenceUpdate /// The type of the object. /// The type of the key. - /// The source of . + /// The source to selectively suppress updates in. /// The ignore function (current,previous)=>{ return true to ignore }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IgnoreUpdateWhen(this IObservable> source, Func ignoreFunction) @@ -2447,7 +2447,7 @@ public static IObservable> IgnoreUpdateWhen /// The type of the object. /// The type of the key. - /// The source of . + /// The source to selectively include updates in. /// The include function (current,previous)=>{ return true to include }. /// An observable which emits change sets and ignores updates equal to the lambda. public static IObservable> IncludeUpdateWhen(this IObservable> source, Func includeFunction) @@ -2466,8 +2466,8 @@ public static IObservable> IncludeUpdateWhen - /// The left of . - /// The right of . + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the left and right values into a destination object. The composite key is not provided in this overload. /// Overload that omits the composite key from the result selector. Delegates to . @@ -2495,8 +2495,8 @@ public static IObservable> IncludeUpdateWhenThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// The left of . - /// The right of . + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the composite key, left value, and right value into a destination object. Example: ((leftKey, rightKey), left, right) => new Result(leftKey, rightKey, left, right). /// An observable changeset keyed by a composite (TLeftKey, TRightKey) tuple. @@ -2545,8 +2545,8 @@ public static IObservable> IncludeUpdateWhen - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -2575,8 +2575,8 @@ public static IObservable> InnerJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2629,7 +2629,7 @@ public static IObservable> InnerJoinMany /// The type of the object. /// The type of the key. - /// The source of . + /// The source to trigger re-evaluation on. /// An observable that emits the same changesets as , unchanged. /// /// @@ -2647,8 +2647,8 @@ public static IObservable> InvokeEvaluate source.Do(changes => changes.Where(u => u.Reason == ChangeReason.Refresh).ForEach(u => u.Current.Evaluate())); /// - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the left value and the optional right into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -2677,8 +2677,8 @@ public static IObservable> LeftJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and optional right into a destination object. Example: (key, left, right) => new Result(key, left, right). /// An observable changeset keyed by . @@ -2726,8 +2726,8 @@ public static IObservable> LeftJoin - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -2756,8 +2756,8 @@ public static IObservable> LeftJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -2810,7 +2810,7 @@ public static IObservable> LeftJoinMany /// The type of the object. /// The type of the key. - /// The source of . + /// The source to apply size limits to. /// The maximum number of items allowed. Must be greater than zero. /// An observable changeset stream with size-limited contents. /// @@ -2894,7 +2894,7 @@ public static IObservable>> LimitSizeTo< /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source of . + /// The source to subscribe to per-item observables from. /// A factory function that produces a child observable for each source item. /// An observable that emits values from all active child observables, interleaved by arrival order. /// @@ -2930,7 +2930,7 @@ public static IObservable MergeMany(t } /// - /// The source of . + /// The source to subscribe to per-item observables from. /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull @@ -3069,9 +3069,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// The second changeset stream to merge with . - /// An optional optional scheduler used when subscribing to the source streams. + /// The source to merge. + /// The second to merge with . + /// An optional used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// or is null. @@ -3090,10 +3090,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// The second changeset stream to merge with . + /// The source to merge. + /// The second to merge with . /// An that comparer to determine which value wins when both sources provide the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. @@ -3113,10 +3113,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// The second changeset stream to merge with . + /// The source to merge. + /// The second to merge with . /// An that equality comparer to detect duplicate values for the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , or is null. @@ -3136,11 +3136,11 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// The second changeset stream to merge with . + /// The source to merge. + /// The second to merge with . /// An that equality comparer to detect duplicate values for the same key. /// An that comparer to determine which value wins when both sources provide the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when both streams complete. If , the output never completes. /// A unified changeset stream containing changes from both sources. /// , , , or is null. @@ -3162,9 +3162,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// An that additional changeset streams to merge with . - /// An optional optional scheduler used when subscribing to the source streams. + /// The source to merge. + /// The additional streams to merge with . + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// or is null. @@ -3183,10 +3183,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// An that additional changeset streams to merge with . + /// The source to merge. + /// The additional streams to merge with . /// An that comparer to determine which value wins when multiple sources provide the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. @@ -3206,10 +3206,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// An that additional changeset streams to merge with . + /// The source to merge. + /// The additional streams to merge with . /// An that equality comparer to detect duplicate values for the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , or is null. @@ -3229,11 +3229,11 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source of . - /// An that additional changeset streams to merge with . + /// The source to merge. + /// The additional streams to merge with . /// An that equality comparer to detect duplicate values for the same key. /// An that comparer to determine which value wins when multiple sources provide the same key. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all streams complete. If , the output never completes. /// A unified changeset stream containing changes from all sources. /// , , , or is null. @@ -3255,8 +3255,8 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source . - /// An optional optional scheduler used when subscribing to the source streams. + /// The source to merge. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// @@ -3287,9 +3287,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source . + /// The source to merge. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. @@ -3310,9 +3310,9 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source . + /// The source to merge. /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// or is null. @@ -3332,10 +3332,10 @@ public static IObservable> MergeChangeSets /// The type of items in the changesets. /// The type of the key identifying items. - /// The source . + /// The source to merge. /// An that equality comparer to detect duplicate values for the same key, suppressing no-op updates. /// An that comparer to determine which value wins when multiple sources provide the same key. The lowest-ordered value is published. - /// An optional optional scheduler used when subscribing to the source streams. + /// An optional used when subscribing to the source streams. /// If (default), the output completes when all source streams have completed. If , the output never completes. /// A unified changeset stream containing changes from all source streams. /// , , or is null. @@ -3359,7 +3359,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3384,7 +3384,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3410,7 +3410,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. /// An that optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. @@ -3437,7 +3437,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying parent items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of whose items each produce a child changeset stream. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a parent item and its key, and returns a child cache changeset stream. Called once per parent Add/Update. /// An that optional equality comparer to suppress no-op child updates. When a child key's new value equals the current value per this comparer, the update is not emitted. /// An that optional comparer to resolve child key conflicts when multiple parents contribute children with the same destination key. The lowest-ordered child value wins. Without a comparer, the first parent to provide a key retains priority. @@ -3510,7 +3510,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3537,7 +3537,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3557,7 +3557,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3584,7 +3584,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3606,7 +3606,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3633,7 +3633,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3654,7 +3654,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3684,7 +3684,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// If (default), a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3723,7 +3723,7 @@ public static IObservable> MergeManyCh /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and its key, and returns a child list changeset stream. /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3745,7 +3745,7 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source of . + /// The source to subscribe to per-item changeset streams from. /// A factory function that receives a source item and returns a child list changeset stream. /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3766,7 +3766,7 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source of . + /// The source to subscribe to per-item observables from. /// A factory function that produces a child observable for each source item. /// An observable of pairing each emission with its source item. /// or is null. @@ -3781,7 +3781,7 @@ public static IObservable> MergeManyItems - /// The source of . + /// The source to subscribe to per-item observables from. /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull @@ -3810,7 +3810,7 @@ public static IObservable> MergeManyItems /// The type of the object. /// The type of the key. - /// The source of . + /// The source to suppress empty changesets from. /// An observable that emits only non-empty changesets. /// is . /// @@ -3830,7 +3830,7 @@ public static IObservable> NotEmpty(thi /// The type of the objects in the source changeset. /// The type of the key. /// The destination type to filter and cast to. - /// The source of . + /// The source to filter by type. /// If , changesets that become empty after filtering are suppressed. /// An observable changeset of items. /// @@ -3860,7 +3860,7 @@ public static IObservable> OfType /// The type of the object. /// The type of the key. - /// The source of . + /// The source to observe item additions in. /// The callback invoked for each added item. Receives the new item and its key. /// A stream that forwards all changesets from unchanged. /// @@ -3894,7 +3894,7 @@ public static IObservable> OnItemAdded( } /// - /// The source of . + /// The source to observe item additions in. /// The callback invoked for each added item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemAdded(this IObservable> source, Action addAction) @@ -3907,7 +3907,7 @@ public static IObservable> OnItemAdded( /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to observe item refresh events in. /// The callback invoked for each refreshed item. Receives the item and its key. /// A stream that forwards all changesets from unchanged. /// @@ -3939,7 +3939,7 @@ public static IObservable> OnItemRefreshed - /// The source of . + /// The source to observe item refresh events in. /// The callback invoked for each refreshed item. Receives only the item (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemRefreshed(this IObservable> source, Action refreshAction) @@ -3953,7 +3953,7 @@ public static IObservable> OnItemRefreshed /// The type of the object. /// The type of the key. - /// The source of . + /// The source to process. /// The callback invoked for each removed item. Receives the removed item and its key. /// /// When (the default), the callback is also invoked for every item still in the cache @@ -4003,7 +4003,7 @@ public static IObservable> OnItemRemoved - /// The source of . + /// The source to observe item removals in. /// The callback invoked for each removed item. Receives only the item (no key). /// When (the default), also invoked for all remaining items on disposal. /// Overload that omits the key from the callback. Delegates to . @@ -4018,7 +4018,7 @@ public static IObservable> OnItemRemoved /// The type of the object. /// The type of the key. - /// The source of . + /// The source to observe item updates in. /// The callback invoked for each updated item. Receives the current value, previous value, and key. /// A stream that forwards all changesets from unchanged. /// @@ -4050,7 +4050,7 @@ public static IObservable> OnItemUpdated - /// The source of . + /// The source to observe item updates in. /// The callback invoked for each updated item. Receives only the current and previous values (no key). /// Overload that omits the key from the callback. Delegates to . public static IObservable> OnItemUpdated(this IObservable> source, Action updateAction) @@ -4063,8 +4063,8 @@ public static IObservable> OnItemUpdated /// The type of the object. /// The type of the key. - /// The source of . - /// An that additional changeset streams to combine with. + /// The source to combine. + /// The additional streams to combine with. /// A changeset stream containing items present in any of the sources. /// /// @@ -4102,7 +4102,7 @@ public static IObservable> Or(this IObs } /// - /// The of changeset streams to combine. + /// The of streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Or(this ICollection>> sources) where TObject : notnull @@ -4119,7 +4119,7 @@ public static IObservable> Or(this ICol /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits change sets. public static IObservable> Or(this IObservableList>> sources) where TObject : notnull @@ -4210,7 +4210,7 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// The source of . + /// The source to populate a target cache from. /// The that will receive the changes. /// An that, when disposed, unsubscribes from the source. /// @@ -4241,7 +4241,7 @@ public static IDisposable PopulateInto(this IObservable - /// The source of . + /// The source to populate a target cache from. /// The that will receive the changes. /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) @@ -4255,7 +4255,7 @@ public static IDisposable PopulateInto(this IObservable - /// The source of . + /// The source to populate a target cache from. /// The that will receive the changes. /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) @@ -4275,7 +4275,7 @@ public static IDisposable PopulateInto(this IObservableThe type of the object. /// The type of the key. /// The type of the destination. - /// The source of . + /// The source to project on each change. /// A function that projects the current snapshot to a result value. /// An observable that emits a projected value after each changeset. /// @@ -4309,7 +4309,7 @@ public static IObservable QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source of . + /// The source to project on each change. /// An observable which emits the query. /// source. public static IObservable> QueryWhenChanged(this IObservable> source) @@ -4327,7 +4327,7 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. /// The type of the value. - /// The source of . + /// The source to project on each change. /// A that should the query be triggered for observables on individual items. /// An observable that emits the query. /// source. @@ -4347,7 +4347,7 @@ public static IObservable> QueryWhenChanged /// The type of the object. /// The type of the key. - /// The source of . + /// The source to share via reference counting. /// A ref-counted observable changeset stream. /// public static IObservable> RefCount(this IObservable> source) @@ -4364,7 +4364,7 @@ public static IObservable> RefCount(thi /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to signal re-evaluation on. /// The item to refresh. /// /// Convenience method that wraps a Refresh inside . A Refresh does not change data in the cache; it signals downstream operators (such as or ) to re-evaluate the item. @@ -4391,8 +4391,8 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The to operate on. - /// The of items items to refresh. + /// The to signal re-evaluation on. + /// The of items to refresh. /// is . public static void Refresh(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4408,7 +4408,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to signal re-evaluation on. /// is . public static void Refresh(this ISourceCache source) where TObject : notnull @@ -4424,7 +4424,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to remove items from. /// The item to remove. /// /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. @@ -4452,7 +4452,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to remove items from. /// The key of the item to remove. /// is . public static void Remove(this ISourceCache source, TKey key) @@ -4470,8 +4470,8 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to operate on. - /// The of items items to remove. + /// The to remove items from. + /// The of items to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable items) where TObject : notnull @@ -4488,7 +4488,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to remove items from. /// The keys to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable keys) @@ -4501,7 +4501,7 @@ public static void Remove(this ISourceCache source } /// - /// The to operate on. + /// The to remove items from. /// The key of the item to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) @@ -4514,7 +4514,7 @@ public static void Remove(this IIntermediateCache } /// - /// The to operate on. + /// The to remove items from. /// The keys to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) @@ -4532,7 +4532,7 @@ public static void Remove(this IIntermediateCache /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to strip keys from, producing an unkeyed list changeset. /// A list changeset stream without key information. /// /// @@ -4555,7 +4555,7 @@ public static IObservable> RemoveKey(this IOb /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to remove a key from. /// The key to remove. /// is . public static void RemoveKey(this ISourceCache source, TKey key) @@ -4572,7 +4572,7 @@ public static void RemoveKey(this ISourceCache sou /// /// The type of the object. /// The type of the key. - /// The to operate on. + /// The to remove keys from. /// The keys to remove. /// is . public static void RemoveKeys(this ISourceCache source, IEnumerable keys) @@ -4585,8 +4585,8 @@ public static void RemoveKeys(this ISourceCache so } /// - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the optional left and right values into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -4615,8 +4615,8 @@ public static IObservable> RightJoinThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the right key, optional left, and right value into a destination object. Example: (rightKey, left, right) => new Result(rightKey, left, right). /// An observable changeset keyed by . @@ -4664,8 +4664,8 @@ public static IObservable> RightJoin - /// The left changeset stream. - /// The right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the optional left value and the right group into a destination object. The key is not provided in this overload. /// Overload that omits the key from the result selector. Delegates to . @@ -4695,8 +4695,8 @@ public static IObservable> RightJoinManyThe item type of the right source. /// The key type of the right source. /// The type produced by . - /// of the left changeset stream. - /// of the right changeset stream. + /// The left to join. + /// The right to join. /// A that maps each right item to the left key it should join on. /// A that combines the key, optional left value, and right group into a destination object. Example: (key, left, group) => new Result(key, left, group). /// An observable changeset keyed by . @@ -4749,7 +4749,7 @@ public static IObservable> RightJoinMany /// The type of the object. /// The type of the key. - /// The source of . + /// The source to skip the initial changeset from. /// An observable that skips the first changeset and forwards all others. /// is . /// @@ -4768,7 +4768,7 @@ public static IObservable> SkipInitial( /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to sort. /// The used to determine sort order. /// A that sort optimisation flags. Specify one or more sort optimisations. /// The number of updates before the entire list is resorted (rather than inline sort). @@ -4795,7 +4795,7 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to sort. /// The comparer observable. /// The sort optimisations. /// The reset threshold. @@ -4816,7 +4816,7 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to sort. /// The comparer observable. /// An that signals the algorithm to re-sort the entire data set. /// The sort optimisations. @@ -4838,7 +4838,7 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to sort. /// The used to determine sort order. /// An that signals the algorithm to re-sort the entire data set. /// The sort optimisations. @@ -4862,7 +4862,7 @@ public static IObservable> Sort(t /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to sort. /// A that expression that selects a comparable value from each item. /// The sort direction. Defaults to ascending. /// A that sort optimization flags. @@ -4896,14 +4896,14 @@ public static IObservable> SortBy /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to prepend an empty changeset to. /// An observable that emits an empty changeset first, then all source changesets. public static IObservable> StartWithEmpty(this IObservable> source) where TObject : notnull where TKey : notnull => source.StartWith(ChangeSet.Empty); /// - /// The source of . + /// The source to prepend an empty changeset to. /// An observable that emits an empty sorted changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4911,7 +4911,7 @@ public static IObservable> StartWithEmpty source.StartWith(SortedChangeSet.Empty); /// - /// The source . + /// The source to prepend an empty changeset to. /// An observable that emits an empty virtual changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4919,7 +4919,7 @@ public static IObservable> StartWithEmpty source.StartWith(VirtualChangeSet.Empty); /// - /// The source . + /// The source to prepend an empty changeset to. /// An observable that emits an empty paged changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4930,7 +4930,7 @@ public static IObservable> StartWithEmptyThe type of the object. /// The type of the key. /// The grouping key type. - /// The source . + /// The source to prepend an empty changeset to. /// An observable that emits an empty group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4942,7 +4942,7 @@ public static IObservable> StartWithEm /// The type of the object. /// The type of the key. /// The grouping key type. - /// The source . + /// The source to prepend an empty changeset to. /// An observable that emits an empty immutable group changeset first, then all source changesets. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) @@ -4952,13 +4952,13 @@ public static IObservable> St /// /// The type of the item. - /// The source of . + /// The source of to prepend an empty changeset to. /// An observable that emits an empty collection first, then all source collections. /// Overload for . public static IObservable> StartWithEmpty(this IObservable> source) => source.StartWith(ReadOnlyCollectionLight.Empty); /// - /// The source of . + /// The source to prepend an initial item to. /// The item to prepend. The key is extracted from . /// Overload for items that implement . Delegates to the explicit key overload. public static IObservable> StartWithItem(this IObservable> source, TObject item) @@ -4976,7 +4976,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source of . + /// The source to prepend an initial item to. /// The item to prepend. /// The key for the item. /// An observable that emits a single-item Add changeset first, then all source changesets. @@ -4997,7 +4997,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source of . + /// The source to create per-item subscriptions from. /// A factory that creates an for each item. Called on Add and Update (for the new value). /// A stream that forwards all changesets from unchanged. /// @@ -5035,7 +5035,7 @@ public static IObservable> SubscribeMany - /// The source of . + /// The source to create per-item subscriptions from. /// A factory that creates an for each item. Receives the item and its key. /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) @@ -5053,7 +5053,7 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// The source of . + /// The source to strip refresh events from. /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull @@ -5106,7 +5106,7 @@ public static IObservable> Switch(this /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to materialize into a collection on each change. /// An observable which emits the read only collection. public static IObservable> ToCollection(this IObservable> source) where TObject : notnull @@ -5119,11 +5119,11 @@ public static IObservable> ToCollection /// The type of the object. /// The type of the key. - /// The source . + /// The source to convert into a keyed changeset stream. /// A that selects the unique key for each item. /// An optional optional: per-item expiration time. Return for no expiration. /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// An optional optional scheduler for expiration timing. + /// An optional for expiration timing. /// An observable changeset stream. /// or is . public static IObservable> ToObservableChangeSet( @@ -5153,11 +5153,11 @@ public static IObservable> ToObservableChangeSet /// The type of the object. /// The type of the key. - /// The source . + /// The source to convert into a keyed changeset stream. /// A that selects the unique key for each item. /// An optional optional: per-item expiration time. Return for no expiration. /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. - /// An optional optional scheduler for expiration timing. + /// An optional for expiration timing. /// An observable changeset stream. /// or is . public static IObservable> ToObservableChangeSet( @@ -5186,7 +5186,7 @@ public static IObservable> ToObservableChangeSet /// The type of the object. /// The type of the key. - /// The source of . + /// The source to watch a single key in. /// The key to watch. /// An that optional comparer to suppress duplicate emissions. Uses default equality if . /// An observable of that reflects the presence or absence of the specified key. @@ -5223,7 +5223,7 @@ public static IObservable> ToObservableOptional /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to watch a single key in. /// The key value. /// When , emits an initial with no value if the key is not present in the cache. /// An optional instance used to determine if an object value has changed. @@ -5256,7 +5256,7 @@ public static IObservable> ToObservableOptional /// The type of the object. /// The type of the key. /// The sort key. - /// The source of . + /// The source to materialize into a sorted collection on each change. /// The sort function. /// The sort order. Defaults to ascending. /// An observable which emits the read only collection. @@ -5270,7 +5270,7 @@ public static IObservable> ToSortedCollection /// The type of the object. /// The type of the key. - /// The source of . + /// The source to materialize into a sorted collection on each change. /// The sort comparer. /// An observable which emits the read only collection. public static IObservable> ToSortedCollection(this IObservable> source, IComparer comparer) @@ -5355,7 +5355,7 @@ public static IObservable> TransformThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to process. /// The tion that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. @@ -5473,7 +5473,7 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to transform asynchronously. /// The async function that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. @@ -5560,7 +5560,7 @@ public static IObservable> TransformAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to transform (items assumed immutable). /// The pure function that maps a source item to a destination item. Must be deterministic: same input always produces equivalent output. /// An observable changeset of transformed items. /// @@ -5603,7 +5603,7 @@ public static IObservable> TransformImmutableThe type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source of . + /// The source to expand each item into multiple children. /// A function that expands a parent item into its children. For or overloads, subsequent changes to the child collection are automatically tracked. /// A that extracts a unique key from each child item. Keys must be unique across ALL parents, not just within one parent. /// An observable changeset of flattened child items. @@ -5660,7 +5660,7 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source of . + /// The source to expand each item into multiple children asynchronously. /// An async function that expands a parent item (and its key) into an of children. /// A that extracts a unique key from each child item. /// An that optional comparer to determine if two child items with the same key are equal. Used to suppress no-op updates. @@ -5762,7 +5762,7 @@ public static IObservable> TransformMa /// The type of the child item keys. /// The type of the source (parent) items. /// The type of the source (parent) keys. - /// The source of . + /// The source to expand each item into multiple children asynchronously with error handling. /// An async function that expands a parent item (and its key) into an of children. /// A that extracts a unique key from each child item. /// A that called when throws. The faulting item is skipped and the stream continues. @@ -5856,7 +5856,7 @@ public static IObservable> TransformMa /// The type of the source items. /// The type of the key. /// The type of the transformed items. - /// The source of . + /// The source to process. /// A function that, given a source item and its key, returns an whose emissions become the transformed values. /// An observable changeset where each key's value is the latest emission from its per-item observable. /// @@ -5950,7 +5950,7 @@ public static IObservable> TransformSafeThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to transform with error handling. /// The tion that produces a from the current source item, the previous source item (if any), and the key. /// A callback invoked when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. /// An optional that, when it emits a predicate, re-transforms all items for which the predicate returns . If , no forced re-transforms occur. @@ -6052,7 +6052,7 @@ public static IObservable> TransformSafeAsyncThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to transform asynchronously with error handling. /// The async function that produces a . /// A that called when throws or faults. The item is skipped and the stream continues. /// An optional that forces re-transformation of matching items. @@ -6123,8 +6123,8 @@ public static IObservable> TransformSafeAsync /// The type of the source items. Must be a reference type. /// The type of the key. - /// The source of . - /// The tion that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. + /// The source to transform into a hierarchical tree. + /// The that returns the key of an item's parent. Return the item's own key (or a non-existent key) for root items. /// An optional that emits a filter predicate for nodes. When the predicate changes, nodes are re-evaluated and filtered. /// An observable changeset of items representing the tree. /// @@ -6199,7 +6199,7 @@ public static IObservable> TransformWithInlineUpd /// The type of the transformed items. Must be a reference type since items are mutated in place. /// The type of the source items. /// The type of the key. - /// The source of . + /// The source to transform with in-place mutation on updates. /// A that called on Add (and optionally Refresh) to create a new . /// A that called on Update. Receives (existingTransformed, newSource). Mutate the existing transformed item to reflect the new source value. Example: (vm, model) => vm.Value = model.Value. /// A that called when or throws. The faulting item is skipped. @@ -6238,7 +6238,7 @@ public static IObservable> TransformWithInlineUpd /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to convert move events into remove/add pairs. /// the same SortedChangeSets, except all moves are replaced with remove + add. public static IObservable> TreatMovesAsRemoveAdd(this IObservable> source) where TObject : notnull @@ -6273,7 +6273,7 @@ static IEnumerable> ReplaceMoves(IChangeSet /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// The source of . + /// The source to evaluate a condition across all items in. /// A factory that produces a condition observable for each item. /// A that predicate applied to each per-item observable's latest value. /// An observable of bool that emits whenever the all-items condition changes. @@ -6309,7 +6309,7 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value. - /// The source of . + /// The source to evaluate a condition across all items in. /// A that selector which returns the target observable. /// The equality condition. /// An observable which boolean values indicating if true. @@ -6326,7 +6326,7 @@ public static IObservable TrueForAll(this IObservab /// The type of the object. /// The type of the key. /// The type of the value emitted by each per-item observable. - /// The source of . + /// The source to evaluate a condition across any item in. /// A factory that produces a condition observable for each item. /// A that predicate applied to each item and its per-item observable's latest value. /// An observable of bool that emits whenever the any-item condition changes. @@ -6350,7 +6350,7 @@ public static IObservable TrueForAny(this IObservab where TValue : notnull => source.TrueFor(observableSelector, items => items.Any(o => o.LatestValue.HasValue && equalityCondition(o.Item, o.LatestValue.Value))); /// - /// The source of . + /// The source to evaluate a condition across any item in. /// A factory that produces a condition observable for each item. /// A that predicate applied to each per-item observable's latest value (without the item). /// This overload accepts a predicate that takes only the value, not the item. Useful when the condition depends only on the observed value. @@ -6372,7 +6372,7 @@ public static IObservable TrueForAny(this IObservab /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to update index positions in. /// An observable that emits the sorted changesets after updating item indices. public static IObservable> UpdateIndex(this IObservable> source) where TObject : IIndexAware @@ -6384,7 +6384,7 @@ public static IObservable> UpdateIndex /// The type of the object. /// The type of the key. - /// The source of . + /// The source to watch a single key in. /// The key to observe. /// An observable of for the specified key only. /// @@ -6412,7 +6412,7 @@ public static IObservable> Watch(this IObse /// /// The type of the object. /// The type of the key. - /// The source of . + /// The source to watch a single key in. /// The key to observe. /// An observable of the item's value whenever it changes for the specified key. /// @@ -6444,7 +6444,7 @@ public static IObservable WatchValue(this IObservableCac } /// - /// The source of . + /// The source to watch a single key in. /// The key to observe. /// This overload extends IObservable<> instead of . public static IObservable WatchValue(this IObservable> source, TKey key) @@ -6462,7 +6462,7 @@ public static IObservable WatchValue(this IObservable /// The type of the object (must implement ). /// The type of the key. - /// The source of . + /// The source to observe property changes on items in. /// The specific property names to monitor. If empty, all property changes trigger emissions. /// An observable that emits the item itself each time a monitored property changes. /// @@ -6502,7 +6502,7 @@ public static IObservable WatchValue(this IObservableThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source of . + /// The source to observe a specific property on items in. /// A that expression selecting the property to monitor. /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of containing both the item and its property value. @@ -6540,7 +6540,7 @@ public static IObservable> WhenPropertyChangedThe type of the object (must implement ). /// The type of the key. /// The type of the monitored property. - /// The source of . + /// The source to observe a specific property value on items in. /// A that expression selecting the property to monitor. /// When (the default), the current property value is emitted immediately for each item upon subscription. /// An observable of property values. The owning item is not included; use if you need it. @@ -6579,7 +6579,7 @@ public static IObservable> WhenPropertyChanged /// The type of the object. /// The type of the key. - /// The source of . + /// The source to filter by change reason. /// The values to filter by. /// An observable which emits a change set with items matching the reasons. /// reasons. @@ -6609,7 +6609,7 @@ public static IObservable> WhereReasonsAre /// The type of the object. /// The type of the key. - /// The source of . + /// The source to filter by excluding change reasons. /// The values to filter by. /// An observable which emits a change set with items not matching the reasons. /// reasons. @@ -6639,8 +6639,8 @@ public static IObservable> WhereReasonsAreNot /// The type of the object. /// The type of the key. - /// The source of . - /// An that additional changeset streams to combine with. + /// The source to combine. + /// The additional streams to combine with. /// A changeset stream containing items present in exactly one source. /// /// @@ -6678,7 +6678,7 @@ public static IObservable> Xor(this IOb } /// - /// The of changeset streams to combine. + /// The of streams to combine. /// This overload accepts a pre-built collection of sources instead of a params array. public static IObservable> Xor(this ICollection>> sources) where TObject : notnull @@ -6695,7 +6695,7 @@ public static IObservable> Xor(this ICo /// /// The type of the object. /// The type of the key. - /// The of changeset streams to combine. + /// The of streams to combine. /// An observable which emits a change set. public static IObservable> Xor(this IObservableList>> sources) where TObject : notnull From 59b789f05047636d387e6a60b0a6f3a6e840787e Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 14:06:19 -0700 Subject: [PATCH 20/23] Remove OnError/OnCompleted rows from synchronous void mutation methods These rows are meaningless on void methods (AddOrUpdate, Clear, EditDiff) that don't participate in Rx streams. Event tables on these methods now only describe the changeset events they produce (Add, Update, Remove, Refresh). --- src/DynamicData/Cache/ObservableCacheEx.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 680e0b060..202f5c939 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -94,8 +94,6 @@ public static IObservable> Adapt(this I /// UpdateProduced when the key already exists. The previous value is included in the changeset. /// RemoveNot produced by this method. /// RefreshNot produced by this method. - /// OnErrorNot applicable (synchronous mutation). - /// OnCompletedNot applicable (synchronous mutation). /// /// /// is . @@ -1024,8 +1022,6 @@ public static IObservable> ChangeKeyUpdateNot produced by this operation. /// RemoveA Remove is emitted for every item currently in the cache. /// RefreshNot produced by this operation. - /// OnErrorNot applicable (synchronous mutation method). - /// OnCompletedNot applicable (synchronous mutation method). /// /// /// is . @@ -1285,8 +1281,6 @@ public static void EditDiff(this ISourceCache sour /// UpdateItems present in both and the cache that differ (per ) produce an Update. /// RemoveItems in the cache whose key is not in produce a Remove. /// RefreshNot produced by this operation. - /// OnErrorNot applicable (synchronous mutation method). - /// OnCompletedNot applicable (synchronous mutation method). /// /// /// , , or is . From c00ea4f090c5745d0a9bcd22c2b9a5b1ba89b05f Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 15:04:55 -0700 Subject: [PATCH 21/23] Fix review findings: dangling prepositions, generic verbs, broken fragments - Replace 'to process.' with operator-specific verbs (6 params) - Rewrite 'to subscribe to per-item X from.' dangling prepositions (20+ params) - Fix 'tion that' broken word fragments in transformFactory params (2) - Fix 'An optional X optional:' double-optional patterns (5+ params) - Rewrite 'a function returning' mangled text in timeSelector params - Add purpose to readOnlyObservableCollection and MergeChangeSets other params --- src/DynamicData/Cache/ObservableCacheEx.cs | 86 +++++++++++----------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index 202f5c939..f0509a023 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -322,7 +322,7 @@ public static IObservableCache AsObservableCache(t /// /// The type of items in the cache. /// The type of the key. - /// The source to process. + /// The source to track for async disposal on removal. /// /// /// Invoked once per subscription, providing an that signals when all @@ -1226,7 +1226,7 @@ public static IObservable> DisposeMany( /// The type object from which the distinct values are selected. /// The type of the key. /// The type of the value. - /// The source to extract distinct values from. + /// The source to extract distinct values. /// The value selector. /// An observable which will emit distinct change sets. /// @@ -1499,7 +1499,7 @@ public static IObservable> Except(this /// The type of the object. /// The type of the key. /// The source to apply time-based expiration to. - /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional that returns the expiration timeout for each item, or for no expiration. /// An observable changeset that includes timer-driven Remove changes for expired items. /// /// When a timer fires, a Remove is emitted for the expired item. @@ -1526,7 +1526,7 @@ public static IObservable> ExpireAfter( /// /// The source to apply time-based expiration to. - /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional that returns the expiration timeout for each item, or for no expiration. /// The used to schedule expiration timers. public static IObservable> ExpireAfter( this IObservable> source, @@ -1541,7 +1541,7 @@ public static IObservable> ExpireAfter( /// /// The source to apply time-based expiration to. - /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional that returns the expiration timeout for each item, or for no expiration. /// An optional polling interval. If specified, items are expired on a polling interval rather than per-item timers. Less accurate but more efficient when many items share similar expiration times. /// /// This overload uses periodic polling instead of per-item timers. Expired items are removed on the next @@ -1560,7 +1560,7 @@ public static IObservable> ExpireAfter( /// /// The source to apply time-based expiration to. - /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional that returns the expiration timeout for each item, or for no expiration. /// An optional if specified, items are expired on a polling interval rather than per-item timers. /// The used to schedule polling and expiration timers. public static IObservable> ExpireAfter( @@ -1583,7 +1583,7 @@ public static IObservable> ExpireAfter( /// The type of the object. /// The type of the key. /// The to operate on. - /// An optional a function returning the expiration timeout for each item, or for no expiration. + /// An optional that returns the expiration timeout for each item, or for no expiration. /// An optional if specified, items are expired on a polling interval rather than per-item timers. /// The scheduler used to schedule expiration timers. Defaults to if . /// An observable that emits the key-value pairs of items removed from the cache by expiration. @@ -1781,7 +1781,7 @@ public static IObservable> FilterImmutable /// The type of the object. /// The type of the key. - /// The source to process. + /// The source to filter using per-item observables. /// A factory that creates an for each item and its key. When the observable emits , the item is included; when , it is excluded. /// A that optional time window to buffer inclusion changes from per-item observables before re-evaluating. /// An that optional scheduler used for buffering. @@ -1848,7 +1848,7 @@ public static IObservable> FilterOnObservable /// The type contained within the observables. /// The source to attach a finally action to. - /// The finally action. + /// The to invoke when the subscription terminates. /// An observable which has always a finally action applied. [Obsolete("This can cause unhandled exception issues so do not use")] public static IObservable FinallySafe(this IObservable source, Action finallyAction) @@ -2240,7 +2240,7 @@ public static IObservable> GroupThe type of the object. /// The type of the key. /// The type of the group key. - /// The source to process. + /// The source to group using per-item observables. /// A factory that creates a group key observable for each item and its key. /// An observable that emits group changesets. Each group is a live sub-cache of its members. /// @@ -2402,7 +2402,7 @@ public static IObservable> Gr /// /// The object of the change set. /// The key of the change set. - /// The source to filter same-reference updates from. + /// The source to suppress same-reference updates in. /// An observable which emits change sets and ignores equal value changes. public static IObservable> IgnoreSameReferenceUpdate(this IObservable> source) where TObject : notnull @@ -2888,7 +2888,7 @@ public static IObservable>> LimitSizeTo< /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source to subscribe to per-item observables from. + /// The source whose items each produce an observable. /// A factory function that produces a child observable for each source item. /// An observable that emits values from all active child observables, interleaved by arrival order. /// @@ -2924,7 +2924,7 @@ public static IObservable MergeMany(t } /// - /// The source to subscribe to per-item observables from. + /// The source whose items each produce an observable. /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable MergeMany(this IObservable> source, Func> observableSelector) where TObject : notnull @@ -3353,7 +3353,7 @@ public static IObservable> MergeChangeSetsThe type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3378,7 +3378,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. /// A merged changeset stream containing items from all active child streams. @@ -3404,7 +3404,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value for a destination key. /// An that optional comparer to resolve key conflicts when multiple child streams provide items with the same destination key. The lowest-ordered item wins. @@ -3504,7 +3504,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3531,7 +3531,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// An that fallback comparer to resolve destination key conflicts when source items compare equal. @@ -3551,7 +3551,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3578,7 +3578,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3600,7 +3600,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3627,7 +3627,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// An that optional equality comparer to suppress updates when the incoming child value equals the current value. @@ -3648,7 +3648,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. /// If , a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3678,7 +3678,7 @@ public static IObservable> MergeManyCh /// The type of the key identifying source cache items. /// The type of items in the child changeset streams. /// The type of the key identifying child items. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child cache changeset stream. /// An that comparer to prioritize between source items when their children produce the same destination key. Lower-ordered source wins. /// If (default), a Refresh in the source stream re-evaluates source priorities. If , Refresh events are ignored for priority recalculation. @@ -3717,7 +3717,7 @@ public static IObservable> MergeManyCh /// The type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and its key, and returns a child list changeset stream. /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3739,7 +3739,7 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of items in the child list changeset streams. - /// The source to subscribe to per-item changeset streams from. + /// The source whose items each produce a child changeset stream. /// A factory function that receives a source item and returns a child list changeset stream. /// An that optional equality comparer to detect duplicate items in the merged list output. /// A merged list changeset stream containing items from all active child streams. @@ -3760,7 +3760,7 @@ public static IObservable> MergeManyChangeSetsThe type of items in the source cache. /// The type of the key identifying source cache items. /// The type of values emitted by child observables. - /// The source to subscribe to per-item observables from. + /// The source whose items each produce an observable. /// A factory function that produces a child observable for each source item. /// An observable of pairing each emission with its source item. /// or is null. @@ -3775,7 +3775,7 @@ public static IObservable> MergeManyItems - /// The source to subscribe to per-item observables from. + /// The source whose items each produce an observable. /// A factory function that receives both the item and its key, and returns a child observable. public static IObservable> MergeManyItems(this IObservable> source, Func> observableSelector) where TObject : notnull @@ -3804,7 +3804,7 @@ public static IObservable> MergeManyItems /// The type of the object. /// The type of the key. - /// The source to suppress empty changesets from. + /// The source to suppress empty changesets. /// An observable that emits only non-empty changesets. /// is . /// @@ -3947,7 +3947,7 @@ public static IObservable> OnItemRefreshed /// The type of the object. /// The type of the key. - /// The source to process. + /// The source to observe item removals in. /// The callback invoked for each removed item. Receives the removed item and its key. /// /// When (the default), the callback is also invoked for every item still in the cache @@ -4204,7 +4204,7 @@ public static IDisposable PopulateFrom(this ISourceCache /// The type of the object. /// The type of the key. - /// The source to populate a target cache from. + /// The source to pipe into a target cache. /// The that will receive the changes. /// An that, when disposed, unsubscribes from the source. /// @@ -4235,7 +4235,7 @@ public static IDisposable PopulateInto(this IObservable - /// The source to populate a target cache from. + /// The source to pipe into a target cache. /// The that will receive the changes. /// Overload that targets an . public static IDisposable PopulateInto(this IObservable> source, IIntermediateCache destination) @@ -4249,7 +4249,7 @@ public static IDisposable PopulateInto(this IObservable - /// The source to populate a target cache from. + /// The source to pipe into a target cache. /// The that will receive the changes. /// Overload that targets a . public static IDisposable PopulateInto(this IObservable> source, LockFreeObservableCache destination) @@ -4743,7 +4743,7 @@ public static IObservable> RightJoinMany /// The type of the object. /// The type of the key. - /// The source to skip the initial changeset from. + /// The source to skip the initial changeset. /// An observable that skips the first changeset and forwards all others. /// is . /// @@ -4991,7 +4991,7 @@ public static IObservable> StartWithItem /// The type of the object. /// The type of the key. - /// The source to create per-item subscriptions from. + /// The source to create a subscription for each item in. /// A factory that creates an for each item. Called on Add and Update (for the new value). /// A stream that forwards all changesets from unchanged. /// @@ -5029,7 +5029,7 @@ public static IObservable> SubscribeMany - /// The source to create per-item subscriptions from. + /// The source to create a subscription for each item in. /// A factory that creates an for each item. Receives the item and its key. /// Overload whose factory receives both the item and the key. See for full details. public static IObservable> SubscribeMany(this IObservable> source, Func subscriptionFactory) @@ -5047,7 +5047,7 @@ public static IObservable> SubscribeMany /// The object of the change set. /// The key of the change set. - /// The source to strip refresh events from. + /// The source to strip refresh events. /// An observable which emits change sets. public static IObservable> SuppressRefresh(this IObservable> source) where TObject : notnull @@ -5115,7 +5115,7 @@ public static IObservable> ToCollectionThe type of the key. /// The source to convert into a keyed changeset stream. /// A that selects the unique key for each item. - /// An optional optional: per-item expiration time. Return for no expiration. + /// An optional that specifies per-item expiration time. Return for no expiration. /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional for expiration timing. /// An observable changeset stream. @@ -5149,7 +5149,7 @@ public static IObservable> ToObservableChangeSetThe type of the key. /// The source to convert into a keyed changeset stream. /// A that selects the unique key for each item. - /// An optional optional: per-item expiration time. Return for no expiration. + /// An optional that specifies per-item expiration time. Return for no expiration. /// The maximum cache size. Oldest items are removed when exceeded. Use -1 for no limit. /// An optional for expiration timing. /// An observable changeset stream. @@ -5349,8 +5349,8 @@ public static IObservable> TransformThe type of the transformed items. /// The type of the source items. /// The type of the key. - /// The source to process. - /// The tion that produces a from the current source item, the previous source item (if any), and the key. + /// The source to transform. + /// The that produces a from the current source item, the previous source item (if any), and the key. /// An observable that, when it emits a predicate, re-transforms all items for which the predicate returns . Re-transformed items are emitted as changes. If , no forced re-transforms occur. /// An observable changeset of transformed items. /// @@ -5850,7 +5850,7 @@ public static IObservable> TransformMa /// The type of the source items. /// The type of the key. /// The type of the transformed items. - /// The source to process. + /// The source to transform using per-item observables. /// A function that, given a source item and its key, returns an whose emissions become the transformed values. /// An observable changeset where each key's value is the latest emission from its per-item observable. /// @@ -5945,7 +5945,7 @@ public static IObservable> TransformSafeThe type of the source items. /// The type of the key. /// The source to transform with error handling. - /// The tion that produces a from the current source item, the previous source item (if any), and the key. + /// The that produces a from the current source item, the previous source item (if any), and the key. /// A callback invoked when throws. Receives an containing the exception and the faulting item. The item is skipped and the stream continues. /// An optional that, when it emits a predicate, re-transforms all items for which the predicate returns . If , no forced re-transforms occur. /// An observable changeset of transformed items. From c9cf4164c6eb5d2ccb187659ed359a4202839003 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 15:36:33 -0700 Subject: [PATCH 22/23] Fix SortAndBind and VirtualiseAndPage params: add type links and purposes - Add type links to all readOnlyObservableCollection params (ReadOnlyObservableCollection{TObject}) - Add type links to targetList params (IList{TObject}) - Add type links to comparer params (IComparer{TObject}) - Add type links to comparerChanged params (IObservable{IComparer{TObject}}) - Add type links to virtualRequests and pageRequests params - Fix source params missing type links ('The source changeset stream.' to proper cref) - Fix 'The size.' useless description - Remove type echoes ('virtualising requests' after IVirtualRequest) --- .../Cache/ObservableCacheEx.SortAndBind.cs | 36 +++++++++---------- .../ObservableCacheEx.VirtualiseAndPage.cs | 24 ++++++------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs index 20ce2016a..9ce7130f2 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.SortAndBind.cs @@ -19,7 +19,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The resulting read only observable collection. + /// The output that will be populated with the sorted results. /// An observable which will emit change sets. /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -40,7 +40,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The resulting read only observable collection. + /// The output that will be populated with the sorted results. /// The with default settings. /// An observable which will emit change sets. /// Creates a and delegates to . @@ -63,7 +63,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The list to bind to. + /// The to bind sorted results to. /// An observable which will emit change sets. /// This is the primary Bind overload for paged data. It applies paged changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -79,7 +79,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The list to bind to. + /// The to bind sorted results to. /// The with default settings. /// An observable which will emit change sets. /// This overload accepts to control reset threshold behavior. @@ -97,7 +97,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The resulting read only observable collection. + /// The output that will be populated with the sorted results. /// An observable which will emit change sets. /// Creates a and delegates to . public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -118,7 +118,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The resulting read only observable collection. + /// The output that will be populated with the sorted results. /// The with default settings. /// An observable which will emit change sets. /// Creates a and delegates to . @@ -141,7 +141,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The list to bind to. + /// The to bind sorted results to. /// An observable which will emit change sets. /// This is the primary Bind overload for virtualized data. It applies virtualized changeset mutations directly to the target list. public static IObservable> Bind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( @@ -157,7 +157,7 @@ public static partial class ObservableCacheEx /// The type of the object. /// The type of the key. /// The source to sort and bind. - /// The list to bind to. + /// The to bind sorted results to. /// The with default settings. /// An observable which will emit change sets. /// This overload accepts to control reset threshold behavior. @@ -204,9 +204,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. - /// The comparer to order the resulting dataset. + /// The source to sort and bind. + /// The to bind sorted results to. Items are inserted, removed, and moved in-place to maintain sort order. + /// The that determines sort order. /// The controlling reset threshold and initial capacity. /// An observable which will emit change sets. /// @@ -250,9 +250,9 @@ public static partial class ObservableCacheEx /// /// The type of the object. /// The type of the key. - /// The source changeset stream. - /// The list to bind to. Items are inserted, removed, and moved in-place to maintain sort order. - /// An observable of comparers which enables the sort order to be changed. + /// The source to sort and bind. + /// The to bind sorted results to. Items are inserted, removed, and moved in-place to maintain sort order. + /// An that emits new comparers to re-sort with. /// The controlling reset threshold and initial capacity. /// An observable which will emit change sets. /// @@ -311,8 +311,8 @@ public static partial class ObservableCacheEx /// /// The source to sort and bind. - /// The resulting read only observable collection. - /// The comparer to order the resulting dataset. + /// The output that will be populated with the sorted results. + /// The that determines sort order. /// The controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, @@ -343,8 +343,8 @@ public static partial class ObservableCacheEx /// /// The source to sort and bind. - /// The resulting read only observable collection. - /// An observable of comparers which enables the sort order to be changed. + /// The output that will be populated with the sorted results. + /// An that emits new comparers to re-sort with. /// The controlling reset threshold and initial capacity. public static IObservable> SortAndBind<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TObject, TKey>( this IObservable> source, diff --git a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs index 4316e0d95..d5a4bd979 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.VirtualiseAndPage.cs @@ -43,8 +43,8 @@ public static IObservable>> So /// The type of the object. /// The type of the key. /// The source to paginate. - /// The comparer to order the resulting dataset. - /// The virtualizing requests (start index and page size). + /// The that determines sort order. + /// The that controls which window of sorted items to include. /// The for controlling virtualization behavior. /// An observable which will emit virtual change sets. /// source. @@ -87,8 +87,8 @@ public static IObservable>> So /// The type of the object. /// The type of the key. /// The source to paginate. - /// An observable of comparers which enables the sort order to be changed. - /// The virtualizing requests (start index and page size). + /// An that emits new comparers to re-sort with. + /// The that controls which window of sorted items to include. /// The for controlling virtualization behavior. /// An observable which will emit virtual change sets. /// source. @@ -130,7 +130,7 @@ public static IObservable>> So /// The type of the object. /// The type of the key. /// The source to paginate. - /// The virtualising requests. + /// The that controls which window of sorted items to include. /// An observable which will emit virtual change sets. /// source. [Obsolete(Constants.VirtualizeIsObsolete)] @@ -151,7 +151,7 @@ public static IObservable> VirtualiseThe type of the object. /// The type of the key. /// The source to limit. - /// The used to determine sort order. + /// The that determines sort order. /// The maximum number of items to return. /// An observable which will emit virtual change sets. /// source. @@ -185,7 +185,7 @@ public static IObservable>> To /// The type of the object. /// The type of the key. /// The source to paginate. - /// The size. + /// The maximum number of items to include. /// An observable which will emit virtual change sets. /// source. /// size;Size should be greater than zero. @@ -235,8 +235,8 @@ public static IObservable>> SortA /// The type of the object. /// The type of the key. /// The source to paginate. - /// The comparer to order the resulting dataset. - /// The page requests (page number and page size). + /// The that determines sort order. + /// The that controls which page of sorted items to include. /// The for controlling paging behavior. /// An observable which will emit paged change sets. /// source. @@ -278,8 +278,8 @@ public static IObservable>> SortA /// The type of the object. /// The type of the key. /// The source to paginate. - /// An observable of comparers which enables the sort order to be changed. - /// The page requests (page number and page size). + /// An that emits new comparers to re-sort with. + /// The that controls which page of sorted items to include. /// The for controlling paging behavior. /// An observable which will emit paged change sets. /// source. @@ -320,7 +320,7 @@ public static IObservable>> SortA /// The type of the object. /// The type of the key. /// The source to paginate. - /// The page requests. + /// The that controls which page of sorted items to include. /// An observable which emits change sets. [Obsolete(Constants.PageIsObsolete)] public static IObservable> Page(this IObservable> source, IObservable pageRequests) From 60e0dfecd881d4a7965037805053f6512d919a29 Mon Sep 17 00:00:00 2001 From: "Darrin W. Cullop" Date: Tue, 14 Apr 2026 15:51:10 -0700 Subject: [PATCH 23/23] Eliminate trailing prepositions in param descriptions Rewrite 'to remove items from.' to 'from which to remove items.' and similar patterns across Remove, RemoveKey, RemoveKeys methods. --- src/DynamicData/Cache/ObservableCacheEx.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/DynamicData/Cache/ObservableCacheEx.cs b/src/DynamicData/Cache/ObservableCacheEx.cs index f0509a023..e532d15d1 100644 --- a/src/DynamicData/Cache/ObservableCacheEx.cs +++ b/src/DynamicData/Cache/ObservableCacheEx.cs @@ -4418,7 +4418,7 @@ public static void Refresh(this ISourceCache sourc /// /// The type of the object. /// The type of the key. - /// The to remove items from. + /// The from which to remove items. /// The item to remove. /// /// Convenience method that wraps a single-item removal inside . The key is extracted from the item using the cache's key selector. @@ -4446,7 +4446,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to remove items from. + /// The from which to remove items. /// The key of the item to remove. /// is . public static void Remove(this ISourceCache source, TKey key) @@ -4464,7 +4464,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to remove items from. + /// The from which to remove items. /// The of items to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable items) @@ -4482,7 +4482,7 @@ public static void Remove(this ISourceCache source /// /// The type of the object. /// The type of the key. - /// The to remove items from. + /// The from which to remove items. /// The keys to remove. /// is . public static void Remove(this ISourceCache source, IEnumerable keys) @@ -4495,7 +4495,7 @@ public static void Remove(this ISourceCache source } /// - /// The to remove items from. + /// The from which to remove items. /// The key of the item to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, TKey key) @@ -4508,7 +4508,7 @@ public static void Remove(this IIntermediateCache } /// - /// The to remove items from. + /// The from which to remove items. /// The keys to remove. /// Overload that targets an . public static void Remove(this IIntermediateCache source, IEnumerable keys) @@ -4549,7 +4549,7 @@ public static IObservable> RemoveKey(this IOb /// /// The type of the object. /// The type of the key. - /// The to remove a key from. + /// The from which to remove a key. /// The key to remove. /// is . public static void RemoveKey(this ISourceCache source, TKey key) @@ -4566,7 +4566,7 @@ public static void RemoveKey(this ISourceCache sou /// /// The type of the object. /// The type of the key. - /// The to remove keys from. + /// The from which to remove keys. /// The keys to remove. /// is . public static void RemoveKeys(this ISourceCache source, IEnumerable keys) @@ -6457,7 +6457,7 @@ public static IObservable WatchValue(this IObservableThe type of the object (must implement ). /// The type of the key. /// The source to observe property changes on items in. - /// The specific property names to monitor. If empty, all property changes trigger emissions. + /// The specific property names to monitor. If empty, all property changes trigger emissions. /// An observable that emits the item itself each time a monitored property changes. /// ///