diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index e5f9f3baf..48b66bc1d 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -12,8 +12,8 @@ jobs:
runs-on: windows-latest
outputs:
nbgv: ${{ steps.nbgv.outputs.SemVer2 }}
- steps:
-
+ steps:
+
- name: Checkout
uses: actions/checkout@v6
with:
@@ -29,6 +29,7 @@ jobs:
8.0.x
9.0.x
10.0.x
+ global-json-file: global.json
cache: true
cache-dependency-path: |
**/Directory.Packages.props
@@ -54,13 +55,13 @@ jobs:
- name: NuGet Restore
run: dotnet restore DynamicData.sln
working-directory: src
-
+
- name: Build
run: dotnet build --no-restore --configuration Release DynamicData.sln
working-directory: src
- name: Run Tests
- run: dotnet test --no-restore --configuration Release DynamicData.sln
+ run: dotnet test --solution DynamicData.sln --no-build --configuration Release --max-parallel-test-modules 4 --maximum-parallel-tests 8
working-directory: src
- name: Pack
diff --git a/.github/workflows/pr-test-coverage.yml b/.github/workflows/pr-test-coverage.yml
index 264c31fa0..778b1d6d9 100644
--- a/.github/workflows/pr-test-coverage.yml
+++ b/.github/workflows/pr-test-coverage.yml
@@ -13,7 +13,7 @@ jobs:
matrix:
configuration: [Release] # future support for more coverage
- runs-on: windows-latest
+ runs-on: windows-latest
if: github.event.workflow_run.conclusion == 'success'
steps:
- name: Checkout
@@ -32,10 +32,13 @@ jobs:
- name: Install .NET
uses: actions/setup-dotnet@v5
with:
- dotnet-version: |
+ dotnet-version: |
6.0.x
7.0.x
8.0.x
+ 9.0.x
+ 10.0.x
+ global-json-file: global.json
- name: Cache SonarCloud packages
uses: actions/cache@v5
@@ -54,11 +57,21 @@ jobs:
- name: Run coverage tests
run: |
- dotnet sonarscanner begin /k:"reactivemarbles_DynamicData" /o:"reactivemarbles" /d:sonar.token="${{ env.SONAR_TOKEN }}" /d:sonar.cs.opencover.reportsPaths=./**/coverage.opencover.xml /d:sonar.host.url="https://sonarcloud.io"
+ dotnet sonarscanner begin /k:"reactivemarbles_DynamicData" /o:"reactivemarbles" /d:sonar.token="${{ env.SONAR_TOKEN }}" /d:sonar.cs.vscoveragexml.reportsPaths=./TestResults/coverage/*.xml /d:sonar.host.url="https://sonarcloud.io"
+ if ($LASTEXITCODE -ne 0) { throw "Sonar scanner initialization failed." }
dotnet build --no-restore --no-incremental --configuration ${{ matrix.configuration }} -p:ContinuousIntegrationBuild=false DynamicData.sln
- dotnet test --no-build --configuration ${{ matrix.configuration }} --collect:"XPlat Code Coverage" --settings coverlet.xml
+ if ($LASTEXITCODE -ne 0) { throw "Coverage build failed." }
+ dotnet test --solution DynamicData.sln --no-build --configuration ${{ matrix.configuration }} --max-parallel-test-modules 4 --maximum-parallel-tests 8 --coverage --coverage-settings coverage.config --coverage-output-format xml --results-directory TestResults/coverage
+ if ($LASTEXITCODE -ne 0) { throw "Coverage tests failed." }
dotnet sonarscanner end /d:sonar.token="${{ env.SONAR_TOKEN }}"
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
working-directory: src
+
+ - name: Upload coverage reports
+ if: always()
+ uses: actions/upload-artifact@v4.6.2
+ with:
+ name: coverage
+ path: src/TestResults/coverage/
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 50f8371d1..757d23324 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -22,7 +22,7 @@ jobs:
outputs:
nbgv: ${{ steps.nbgv.outputs.SemVer2 }}
steps:
-
+
- name: Checkout
uses: actions/checkout@v6
with:
@@ -48,6 +48,7 @@ jobs:
8.0.x
9.0.x
10.0.x
+ global-json-file: global.json
cache: true
cache-dependency-path: |
**/Directory.Packages.props
@@ -113,7 +114,7 @@ jobs:
working-directory: src
- name: Run Tests
- run: dotnet test --no-restore --configuration Release DynamicData.sln
+ run: dotnet test --solution DynamicData.sln --no-restore --configuration Release
working-directory: src
- name: Pack
diff --git a/.gitignore b/.gitignore
index cc0cf38bc..d4768f880 100644
--- a/.gitignore
+++ b/.gitignore
@@ -369,3 +369,5 @@ src/*.Tests/API/ApiApprovalTests.*.received.txt
# JetBrains
.idea/
+
+.dotnet-home/
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..19b6f3396
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Building and testing
+
+Install the .NET SDK version recorded in `global.json`. This branch uses .NET 11
+RC1 (`11.0.100-rc.1.26425.128`) for local builds and CI. The SDK selection is
+exact so an installed preview or a newer SDK cannot silently change the build.
+`allowPrerelease` must be enabled because .NET classifies release candidates as
+prerelease SDKs; the version pin selects the RC explicitly.
+
+From the repository root:
+
+```powershell
+dotnet restore src/DynamicData.sln
+dotnet build src/DynamicData.sln --configuration Release --no-restore
+dotnet test --solution src/DynamicData.sln --configuration Release --no-build
+```
+
+`DynamicData` is the lean ReactiveUI.Primitives package. `DynamicData.Reactive`
+compiles the shared sources with `REACTIVE_SHIM` and preserves the System.Reactive
+API conventions. Changes to shared operators must preserve both variants.
+
+Tests use TUnit and Microsoft.Testing.Platform. Use native, awaited TUnit assertions
+and virtual time or explicit synchronization for asynchronous behavior. Collect
+coverage for the shipping assemblies, including their auto-properties, with:
+
+```powershell
+dotnet test --solution src/DynamicData.sln --configuration Release --no-build --coverage --coverage-settings src/coverage.config --coverage-output-format cobertura
+```
+
+The coverage configuration selects the two shipping assemblies. It does not
+exclude obsolete operators or uncovered source files.
+
+Performance changes should include a benchmark for the affected operation and
+regression tests covering observable values, completion, errors, and disposal.
+Run the cache snapshot comparison with:
+
+```powershell
+dotnet run --project src/DynamicData.Benchmarks --configuration Release -- --filter '*ToCollection*'
+```
+
+Public API tests compare generated signatures against the framework-specific files
+in `src/DynamicData.Tests/API`. A mismatch writes a `.received.txt` file next to the
+reviewed `.verified.txt` baseline. Review the API diff before updating a baseline;
+do not accept generated changes just to make the test pass.
diff --git a/NonProduction/DynamicData.Profile/DynamicData.Profile.csproj b/NonProduction/DynamicData.Profile/DynamicData.Profile.csproj
index 504b3165c..8e7cb5536 100644
--- a/NonProduction/DynamicData.Profile/DynamicData.Profile.csproj
+++ b/NonProduction/DynamicData.Profile/DynamicData.Profile.csproj
@@ -14,7 +14,6 @@
-
diff --git a/README.md b/README.md
index 3b916a7da..7ca2a8e10 100644
--- a/README.md
+++ b/README.md
@@ -313,9 +313,17 @@ var myPeopleObservable = myPeople.Connect();
var countObservable = myPeopleObservable.Count();
var maxObservable = myPeopleObservable.Max(p => p.Age);
var minObservable = myPeopleObservable.Min(p => p.Age);
-var stdDevObservable = myPeopleObservable.StdDev(p => p.Age);
+var stdDevObservable = myPeopleObservable.StdDev(p => p.Age, 0);
var avgObservable = myPeopleObservable.Avg(p => p.Age);
```
+`StdDev` computes the sample standard deviation: `sqrt(M2 / (count - 1))`,
+where `M2` is the sum of squared differences from the mean. For example, values
+`2, 4, 6` produce `2`. It returns the supplied fallback when fewer than two
+values remain. This corrects the earlier formula, which divided by `count - 1`
+after taking the square root. Integral and decimal selectors use decimal
+accumulators, whose central moments must fit in the decimal range; floating-point
+selectors retain double-precision rounding limits.
+
More aggregating operators will be added soon.
#### Logical Operators
diff --git a/global.json b/global.json
new file mode 100644
index 000000000..13c274d29
--- /dev/null
+++ b/global.json
@@ -0,0 +1,10 @@
+{
+ "sdk": {
+ "version": "11.0.100-rc.1.26425.128",
+ "rollForward": "disable",
+ "allowPrerelease": true
+ },
+ "test": {
+ "runner": "Microsoft.Testing.Platform"
+ }
+}
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 7d002a3bb..94c96f6a6 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -3,7 +3,7 @@
true
- $(NoWarn);1591;1701;1702;1705;VSX1000;CA1510
+ $(NoWarn);1701;1702;1705;VSX1000;CA1510
AnyCPU
enable
latest
@@ -22,14 +22,15 @@
logo.png
README.md
true
-
+
- true
+ true
true
$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
- CS8600;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8623;CS8624;CS8625;CS8626;CS8627;CS8628;CS8629;CS8630;CS8634;CS8766;CS8767
+ CS8600;CS8602;CS8603;CS8604;CS8605;CS8606;CS8607;CS8608;CS8609;CS8610;CS8611;CS8612;CS8613;CS8614;CS8615;CS8616;CS8617;CS8618;CS8619;CS8620;CS8621;CS8622;CS8623;CS8624;CS8625;CS8626;CS8627;CS8628;CS8629;CS8630;CS8634;CS8766;CS8767
+ enable
@@ -38,33 +39,54 @@
false
+ false
+
+ $(WarningsAsErrors);CS4014;CS8785;TUnit0030
+
+
+
+ $(MSBuildThisFileDirectory)
+
+
+
+
+ true
+ true
+ true
+
+
+
+ $(Features);runtime-async=on
+
+
-
+
-
-
- $(MSBuildThisFileDirectory)
-
-
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index d341fbbbd..0a63b1424 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -6,7 +6,7 @@
- $([System.Text.RegularExpressions.Regex]::Replace(%(Filename), '\.[^\.]+$', '.cs'))
+ $([System.Text.RegularExpressions.Regex]::Replace('%(Filename)', '\.[^\.]+$', '.cs'))
@@ -14,11 +14,18 @@
$(DefineConstants);P_LINQ;SUPPORTS_BINDINGLIST
-
- $(DefineConstants);NETSTANDARD;P_LINQ;SUPPORTS_BINDINGLIST;SUPPORTS_ASYNC_DISPOSABLE
+
+ $(DefineConstants);NETSTANDARD;P_LINQ;SUPPORTS_BINDINGLIST;SUPPORTS_ASYNC_DISPOSABLE;SUPPORTS_DICTIONARY_MUTATION_DURING_ENUMERATION
-
- $(DefineConstants);SUPPORTS_DICTIONARY_MUTATION_DURING_ENUMERATION
-
+
+
+
+
+
+
diff --git a/src/DynamicData.Benchmarks/Cache/DeliveryQueueBenchmarks.cs b/src/DynamicData.Benchmarks/Cache/DeliveryQueueBenchmarks.cs
index f5e397006..35795043a 100644
--- a/src/DynamicData.Benchmarks/Cache/DeliveryQueueBenchmarks.cs
+++ b/src/DynamicData.Benchmarks/Cache/DeliveryQueueBenchmarks.cs
@@ -2,16 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System;
-using System.Linq;
-using System.Reactive.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-using BenchmarkDotNet.Attributes;
-
-using DynamicData.Binding;
-
namespace DynamicData.Benchmarks.Cache;
///
diff --git a/src/DynamicData.Benchmarks/Cache/DisposeMany_Cache.cs b/src/DynamicData.Benchmarks/Cache/DisposeMany_Cache.cs
index 1e4f83e65..fc1b34c15 100644
--- a/src/DynamicData.Benchmarks/Cache/DisposeMany_Cache.cs
+++ b/src/DynamicData.Benchmarks/Cache/DisposeMany_Cache.cs
@@ -2,10 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache
{
[MemoryDiagnoser]
diff --git a/src/DynamicData.Benchmarks/Cache/EditDiff.cs b/src/DynamicData.Benchmarks/Cache/EditDiff.cs
index a6b4fd53d..a3f408df8 100644
--- a/src/DynamicData.Benchmarks/Cache/EditDiff.cs
+++ b/src/DynamicData.Benchmarks/Cache/EditDiff.cs
@@ -1,12 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reactive.Linq;
-
-using BenchmarkDotNet.Attributes;
-
-using DynamicData.Kernel;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -49,7 +40,7 @@ public void OptionalAddsAndRemoves(int maxItems)
.Range(0, MaxItems)
.Select(n => (n % 2) == 0
? new Person(n, "Name")
- : Optional.None())
+ : Optional.None)
.ToObservable()
.EditDiff(p => p.Id)
.Subscribe();
diff --git a/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForSource.cs b/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForSource.cs
index 3c437f89f..ff3e3699f 100644
--- a/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForSource.cs
+++ b/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForSource.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-
-using Bogus;
+using Bogus;
namespace DynamicData.Benchmarks.Cache;
diff --git a/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForStream.cs b/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForStream.cs
index a13cefbf0..f7703de96 100644
--- a/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForStream.cs
+++ b/src/DynamicData.Benchmarks/Cache/ExpireAfter_Cache_ForStream.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
using Bogus;
namespace DynamicData.Benchmarks.Cache;
@@ -113,7 +106,7 @@ public ExpireAfter_Cache_ForStream()
[Benchmark]
public void RandomizedEditsAndExpirations()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.ExpireAfter(
diff --git a/src/DynamicData.Benchmarks/Cache/FilterImmutable.cs b/src/DynamicData.Benchmarks/Cache/FilterImmutable.cs
index 6bde5da17..1faf82f25 100644
--- a/src/DynamicData.Benchmarks/Cache/FilterImmutable.cs
+++ b/src/DynamicData.Benchmarks/Cache/FilterImmutable.cs
@@ -1,9 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -58,7 +52,7 @@ public FilterImmutable()
[Benchmark]
public void Adds()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.FilterImmutable(static item => item.IsIncluded)
@@ -73,7 +67,7 @@ public void Adds()
[Benchmark]
public void AddsAndReplacements()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.FilterImmutable(static item => item.IsIncluded)
@@ -91,7 +85,7 @@ public void AddsAndReplacements()
[Benchmark]
public void AddsAndRemoves()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.FilterImmutable(static item => item.IsIncluded)
@@ -109,7 +103,7 @@ public void AddsAndRemoves()
[Benchmark]
public void AddsReplacementsAndRemoves()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.FilterImmutable(static item => item.IsIncluded)
diff --git a/src/DynamicData.Benchmarks/Cache/Filter_Cache_WithPredicateState.cs b/src/DynamicData.Benchmarks/Cache/Filter_Cache_WithPredicateState.cs
index 0404b7c54..e5bc6797e 100644
--- a/src/DynamicData.Benchmarks/Cache/Filter_Cache_WithPredicateState.cs
+++ b/src/DynamicData.Benchmarks/Cache/Filter_Cache_WithPredicateState.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
using Bogus;
namespace DynamicData.Benchmarks.Cache;
@@ -99,7 +92,6 @@ public Filter_Cache_WithPredicateState()
}
_changeSets = changeSets.MoveToImmutable();
-
var predicateStates = ImmutableArray.CreateBuilder(initialCapacity: 5_000);
while (predicateStates.Count < predicateStates.Capacity)
predicateStates.Add(randomizer.Int());
@@ -109,8 +101,8 @@ public Filter_Cache_WithPredicateState()
[Benchmark(Baseline = true)]
public void RandomizedEditsAndStateChanges()
{
- using var source = new Subject>();
- using var predicateState = new Subject();
+ using var source = new Signal>();
+ using var predicateState = new Signal();
using var subscription = source
.Filter(
diff --git a/src/DynamicData.Benchmarks/Cache/SortAndBindChange.cs b/src/DynamicData.Benchmarks/Cache/SortAndBindChange.cs
index 484e544e1..cbf4340bb 100644
--- a/src/DynamicData.Benchmarks/Cache/SortAndBindChange.cs
+++ b/src/DynamicData.Benchmarks/Cache/SortAndBindChange.cs
@@ -1,11 +1,3 @@
-using System;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Reactive.Disposables;
-using System.Reactive.Subjects;
-using BenchmarkDotNet.Attributes;
-using DynamicData.Binding;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -19,11 +11,10 @@ private record Item(string Name, int Id, int Ranking);
.Ascending(i => i.Ranking)
.ThenByAscending(i => i.Name);
-
- Subject> _newSubject = new();
- Subject> _newSubjectOptimised = new();
- Subject> _oldSubject = new();
- Subject> _oldSubjectOptimised = new();
+ Signal> _newSubject = new();
+ Signal> _newSubjectOptimised = new();
+ Signal> _oldSubject = new();
+ Signal> _oldSubjectOptimised = new();
private IDisposable? _cleanUp;
@@ -32,22 +23,18 @@ private record Item(string Name, int Id, int Ranking);
private ReadOnlyObservableCollection- ? _oldList;
private ReadOnlyObservableCollection
- ? _oldListOptimised;
-
-
[Params(10, 100, 1_000, 10_000, 50_000)]
public int Count { get; set; }
-
[GlobalSetup]
public void SetUp()
{
- _oldSubject = new Subject>();
- _oldSubjectOptimised = new Subject>();
- _newSubject = new Subject>();
- _newSubjectOptimised = new Subject>();
-
+ _oldSubject = new Signal>();
+ _oldSubjectOptimised = new Signal>();
+ _newSubject = new Signal>();
+ _newSubjectOptimised = new Signal>();
- _cleanUp = new CompositeDisposable
+ _cleanUp = new CompositeDisposable
(
_newSubject.SortAndBind(out var newList, _comparer).Subscribe(),
_newSubjectOptimised.SortAndBind(out var optimisedList, _comparer, new SortAndBindOptions
@@ -65,8 +52,6 @@ public void SetUp()
_oldList = oldList;
_oldListOptimised = oldOptimisedList;
-
-
var changeSet = new ChangeSet
- (Count);
foreach (var i in Enumerable.Range(1, Count))
{
@@ -84,7 +69,6 @@ public void SetUp()
[Benchmark(Baseline = true)]
public void Old() => RunTest(_oldSubject, _oldList!);
-
[Benchmark]
public void OldOptimized() => RunTest(_oldSubjectOptimised, _oldListOptimised!);
@@ -94,8 +78,7 @@ public void SetUp()
[Benchmark]
public void NewOptimized() => RunTest(_newSubjectOptimised, _newListOptimised!);
-
- void RunTest(Subject> subject, ReadOnlyObservableCollection
- list)
+ void RunTest(Signal> subject, ReadOnlyObservableCollection
- list)
{
var original = list[Count / 2];
var updated = original with { Ranking = _random.Next(1, 1000) };
@@ -106,6 +89,5 @@ void RunTest(Subject> subject, ReadOnlyObservableCollectio
});
}
-
public void Dispose() => _cleanUp?.Dispose();
-}
\ No newline at end of file
+}
diff --git a/src/DynamicData.Benchmarks/Cache/SortAndBindInitial.cs b/src/DynamicData.Benchmarks/Cache/SortAndBindInitial.cs
index a27b082bd..8d13605c0 100644
--- a/src/DynamicData.Benchmarks/Cache/SortAndBindInitial.cs
+++ b/src/DynamicData.Benchmarks/Cache/SortAndBindInitial.cs
@@ -1,10 +1,3 @@
-using BenchmarkDotNet.Attributes;
-using System;
-using System.Linq;
-using System.Reactive.Disposables;
-using System.Reactive.Subjects;
-using DynamicData.Binding;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -17,27 +10,24 @@ private record Item(string Name, int Id, int Ranking);
private readonly SortExpressionComparer
- _comparer = SortExpressionComparer
- .Ascending(i => i.Ranking).ThenByAscending(i => i.Name);
-
- Subject> _newSubject = new();
- Subject> _newSubjectOptimised = new();
- Subject> _oldSubject = new();
- Subject> _oldSubjectOptimised = new();
+ Signal> _newSubject = new();
+ Signal> _newSubjectOptimised = new();
+ Signal> _oldSubject = new();
+ Signal> _oldSubjectOptimised = new();
private IDisposable? _cleanUp;
private ChangeSet
- ? _changeSet;
-
[Params(10, 100, 1_000, 10_000, 50_000)]
public int Count { get; set; }
-
[GlobalSetup]
public void SetUp()
{
- _oldSubject = new Subject>();
- _oldSubjectOptimised = new Subject>();
- _newSubject = new Subject>();
- _newSubjectOptimised = new Subject>();
+ _oldSubject = new Signal>();
+ _oldSubjectOptimised = new Signal>();
+ _newSubject = new Signal>();
+ _newSubjectOptimised = new Signal>();
var changeSet = new ChangeSet
- (Count);
foreach (var i in Enumerable.Range(1, Count))
@@ -63,7 +53,6 @@ public void SetUp()
);
}
-
[Benchmark(Baseline = true)]
public void Old() => _oldSubject.OnNext(_changeSet!);
@@ -76,6 +65,5 @@ public void SetUp()
[Benchmark]
public void NewOptimized() => _newSubjectOptimised.OnNext(_changeSet!);
-
public void Dispose() => _cleanUp?.Dispose();
-}
\ No newline at end of file
+}
diff --git a/src/DynamicData.Benchmarks/Cache/SourceCache.cs b/src/DynamicData.Benchmarks/Cache/SourceCache.cs
index f2157221d..567f88803 100644
--- a/src/DynamicData.Benchmarks/Cache/SourceCache.cs
+++ b/src/DynamicData.Benchmarks/Cache/SourceCache.cs
@@ -2,11 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-
namespace DynamicData.Benchmarks.Cache
{
public class BenchmarkItem
diff --git a/src/DynamicData.Benchmarks/Cache/StatelessFiltering.cs b/src/DynamicData.Benchmarks/Cache/StatelessFiltering.cs
index b4a806afb..34161c08f 100644
--- a/src/DynamicData.Benchmarks/Cache/StatelessFiltering.cs
+++ b/src/DynamicData.Benchmarks/Cache/StatelessFiltering.cs
@@ -1,9 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -53,7 +47,7 @@ public StatelessFiltering()
[Benchmark(Baseline = true)]
public void Filter()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Filter(static item => item.IsIncluded)
@@ -67,7 +61,7 @@ public void Filter()
[Benchmark]
public void FilterImmutable()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.FilterImmutable(static item => item.IsIncluded)
diff --git a/src/DynamicData.Benchmarks/Cache/StatelessTransforming.cs b/src/DynamicData.Benchmarks/Cache/StatelessTransforming.cs
index 9328dd956..a0179332e 100644
--- a/src/DynamicData.Benchmarks/Cache/StatelessTransforming.cs
+++ b/src/DynamicData.Benchmarks/Cache/StatelessTransforming.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -54,7 +47,7 @@ public StatelessTransforming()
[Benchmark(Baseline = true)]
public void Transform()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Transform(static item => item.Name)
@@ -68,7 +61,7 @@ public void Transform()
[Benchmark]
public void TransformImmutable()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.TransformImmutable(static item => item.Name)
diff --git a/src/DynamicData.Benchmarks/Cache/Sum_Cache.cs b/src/DynamicData.Benchmarks/Cache/Sum_Cache.cs
index 008192d9b..d0ada2daf 100644
--- a/src/DynamicData.Benchmarks/Cache/Sum_Cache.cs
+++ b/src/DynamicData.Benchmarks/Cache/Sum_Cache.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Reactive.Subjects;
using BenchmarkDotNet.Attributes;
@@ -110,7 +109,7 @@ private static IChangeSet
- BuildSeed(Item[] items)
private static void Run(IChangeSet
- ? seed, IReadOnlyList> changeSets)
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Sum(static item => item.Value)
diff --git a/src/DynamicData.Benchmarks/Cache/ToCollection.cs b/src/DynamicData.Benchmarks/Cache/ToCollection.cs
new file mode 100644
index 000000000..bddb23b0b
--- /dev/null
+++ b/src/DynamicData.Benchmarks/Cache/ToCollection.cs
@@ -0,0 +1,58 @@
+// Copyright (c) 2011-2026 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.
+
+using DynamicData.Kernel;
+
+namespace DynamicData.Benchmarks.Cache;
+
+[MemoryDiagnoser]
+public class ToCollection
+{
+ private IChangeSet[] _changes = null!;
+
+ [Params(1, 100)]
+ public int Count { get; set; }
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ var cache = new ChangeAwareCache();
+ _changes = new IChangeSet[Count];
+ for (var i = 0; i < Count; i++)
+ {
+ cache.AddOrUpdate(i, i);
+ _changes[i] = cache.CaptureChanges();
+ }
+ }
+
+ [Benchmark(Baseline = true)]
+ public int QueryProjection()
+ {
+ using var source = new Signal>();
+ var count = 0;
+ using var subscription = source
+ .QueryWhenChanged(query => new ReadOnlyCollectionLight(query.Items))
+ .Subscribe(items => count += items.Count);
+ foreach (var change in _changes)
+ {
+ source.OnNext(change);
+ }
+
+ return count;
+ }
+
+ [Benchmark]
+ public int DirectSnapshot()
+ {
+ using var source = new Signal>();
+ var count = 0;
+ using var subscription = source.ToCollection().Subscribe(items => count += items.Count);
+ foreach (var change in _changes)
+ {
+ source.OnNext(change);
+ }
+
+ return count;
+ }
+}
diff --git a/src/DynamicData.Benchmarks/Cache/ToObservableChangeSet_Cache.cs b/src/DynamicData.Benchmarks/Cache/ToObservableChangeSet_Cache.cs
index eca407d03..d90164cf7 100644
--- a/src/DynamicData.Benchmarks/Cache/ToObservableChangeSet_Cache.cs
+++ b/src/DynamicData.Benchmarks/Cache/ToObservableChangeSet_Cache.cs
@@ -1,11 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Columns;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -51,7 +43,7 @@ static ToObservableChangeSet_Cache()
[Arguments(1_000, 1_000)]
public void AddsUpdatesAndFinalization(int itemCount, int sizeLimit)
{
- using var source = new Subject
- ();
+ using var source = new Signal
- ();
using var subscription = source
.ToObservableChangeSet(
diff --git a/src/DynamicData.Benchmarks/Cache/TransformImmutable.cs b/src/DynamicData.Benchmarks/Cache/TransformImmutable.cs
index 3bbd28d8f..d6d6a29b7 100644
--- a/src/DynamicData.Benchmarks/Cache/TransformImmutable.cs
+++ b/src/DynamicData.Benchmarks/Cache/TransformImmutable.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
@@ -59,7 +52,7 @@ public TransformImmutable()
[Benchmark]
public void Adds()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.TransformImmutable(static item => item.Name)
@@ -74,7 +67,7 @@ public void Adds()
[Benchmark]
public void AddsAndReplacements()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.TransformImmutable(static item => item.Name)
@@ -92,7 +85,7 @@ public void AddsAndReplacements()
[Benchmark]
public void AddsAndRemoves()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.TransformImmutable(static item => item.Name)
@@ -110,7 +103,7 @@ public void AddsAndRemoves()
[Benchmark]
public void AddsReplacementsAndRemoves()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.TransformImmutable(static item => item.Name)
diff --git a/src/DynamicData.Benchmarks/Cache/TransformMany.cs b/src/DynamicData.Benchmarks/Cache/TransformMany.cs
index 5b91eaa41..5de8d8524 100644
--- a/src/DynamicData.Benchmarks/Cache/TransformMany.cs
+++ b/src/DynamicData.Benchmarks/Cache/TransformMany.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reactive.Linq;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.Cache;
[MemoryDiagnoser]
diff --git a/src/DynamicData.Benchmarks/DynamicData.Benchmarks.csproj b/src/DynamicData.Benchmarks/DynamicData.Benchmarks.csproj
index 451ac4697..9a3ad1e6a 100644
--- a/src/DynamicData.Benchmarks/DynamicData.Benchmarks.csproj
+++ b/src/DynamicData.Benchmarks/DynamicData.Benchmarks.csproj
@@ -1,28 +1,46 @@
-
+
-
- Exe
- net9.0
- AnyCPU
- false
- ;1591;1701;1702;1705;CA1822;CA1001
-
+
+ Exe
+ net10.0
+ AnyCPU
+ false
+ ;1701;1702;1705;CA1822;CA1001
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DynamicData.Benchmarks/List/DisposeMany_List.cs b/src/DynamicData.Benchmarks/List/DisposeMany_List.cs
index 53cbe5d5e..100d8dbf6 100644
--- a/src/DynamicData.Benchmarks/List/DisposeMany_List.cs
+++ b/src/DynamicData.Benchmarks/List/DisposeMany_List.cs
@@ -1,12 +1,7 @@
-// Copyright (c) 2011-2019 Roland Pheasant. All rights reserved.
+// Copyright (c) 2011-2019 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.
-using System;
-using System.Reactive.Disposables;
-
-using BenchmarkDotNet.Attributes;
-
namespace DynamicData.Benchmarks.List
{
[MemoryDiagnoser]
diff --git a/src/DynamicData.Benchmarks/List/ExpireAfter_List.cs b/src/DynamicData.Benchmarks/List/ExpireAfter_List.cs
index ec9a39316..1a68f00d4 100644
--- a/src/DynamicData.Benchmarks/List/ExpireAfter_List.cs
+++ b/src/DynamicData.Benchmarks/List/ExpireAfter_List.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-
-using Bogus;
+using Bogus;
namespace DynamicData.Benchmarks.List;
diff --git a/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedBoundedEdits.cs b/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedBoundedEdits.cs
index 6e4ab39ee..d20b7bb30 100644
--- a/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedBoundedEdits.cs
+++ b/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedBoundedEdits.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Reactive.Subjects;
using System.Reflection;
-using BenchmarkDotNet.Attributes;
using Bogus;
@@ -44,7 +38,7 @@ public Filter_List_Static_RandomizedBoundedEdits()
[Benchmark(Baseline = true)]
public void CurrentImplementation()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Filter(Item.FilterByIsIncluded)
diff --git a/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedUnboundedEdits.cs b/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedUnboundedEdits.cs
index e9065ef17..8691e2d22 100644
--- a/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedUnboundedEdits.cs
+++ b/src/DynamicData.Benchmarks/List/Filter_List_Static_RandomizedUnboundedEdits.cs
@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Reactive.Subjects;
using System.Reflection;
-using BenchmarkDotNet.Attributes;
using Bogus;
@@ -42,7 +36,7 @@ public Filter_List_Static_RandomizedUnboundedEdits()
[Benchmark(Baseline = true)]
public void CurrentImplementation()
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Filter(Item.FilterByIsIncluded)
diff --git a/src/DynamicData.Benchmarks/List/Filter_List_WithPredicateState.cs b/src/DynamicData.Benchmarks/List/Filter_List_WithPredicateState.cs
index 3707767be..846e20006 100644
--- a/src/DynamicData.Benchmarks/List/Filter_List_WithPredicateState.cs
+++ b/src/DynamicData.Benchmarks/List/Filter_List_WithPredicateState.cs
@@ -1,10 +1,3 @@
-using System;
-using System.Collections.Immutable;
-using System.Linq;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-
using Bogus;
namespace DynamicData.Benchmarks.List;
@@ -34,8 +27,8 @@ public Filter_List_WithPredicateState()
[Benchmark(Baseline = true)]
public void RandomizedEditsAndStateChanges()
{
- using var source = new Subject>();
- using var predicateState = new Subject();
+ using var source = new Signal>();
+ using var predicateState = new Signal();
using var subscription = source
.Filter(
diff --git a/src/DynamicData.Benchmarks/List/GroupAdd.cs b/src/DynamicData.Benchmarks/List/GroupAdd.cs
index 92572496e..0037925eb 100644
--- a/src/DynamicData.Benchmarks/List/GroupAdd.cs
+++ b/src/DynamicData.Benchmarks/List/GroupAdd.cs
@@ -2,12 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System;
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-
namespace DynamicData.Benchmarks.List
{
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
diff --git a/src/DynamicData.Benchmarks/List/GroupRemove.cs b/src/DynamicData.Benchmarks/List/GroupRemove.cs
index d4ba95e05..dee140d07 100644
--- a/src/DynamicData.Benchmarks/List/GroupRemove.cs
+++ b/src/DynamicData.Benchmarks/List/GroupRemove.cs
@@ -2,12 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System;
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-
namespace DynamicData.Benchmarks.List
{
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
diff --git a/src/DynamicData.Benchmarks/List/SourceList.cs b/src/DynamicData.Benchmarks/List/SourceList.cs
index 6556d6ecf..1c29970e5 100644
--- a/src/DynamicData.Benchmarks/List/SourceList.cs
+++ b/src/DynamicData.Benchmarks/List/SourceList.cs
@@ -2,11 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System.Linq;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Jobs;
-
namespace DynamicData.Benchmarks.List
{
[SimpleJob(RuntimeMoniker.NetCoreApp31)]
diff --git a/src/DynamicData.Benchmarks/List/Sum_List.cs b/src/DynamicData.Benchmarks/List/Sum_List.cs
index 87a90c97e..fd7ba6359 100644
--- a/src/DynamicData.Benchmarks/List/Sum_List.cs
+++ b/src/DynamicData.Benchmarks/List/Sum_List.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Reactive.Subjects;
using BenchmarkDotNet.Attributes;
@@ -107,7 +106,7 @@ private static IChangeSet
- BuildSeed(Item[] items)
private static void Run(IChangeSet
- ? seed, IReadOnlyList> changeSets)
{
- using var source = new Subject>();
+ using var source = new Signal>();
using var subscription = source
.Sum(static item => item.Value)
diff --git a/src/DynamicData.Benchmarks/List/ToObservableChangeSet_List.cs b/src/DynamicData.Benchmarks/List/ToObservableChangeSet_List.cs
index 0908c20f9..799ed91d4 100644
--- a/src/DynamicData.Benchmarks/List/ToObservableChangeSet_List.cs
+++ b/src/DynamicData.Benchmarks/List/ToObservableChangeSet_List.cs
@@ -1,9 +1,3 @@
-using System;
-using System.Reactive.Subjects;
-
-using BenchmarkDotNet.Attributes;
-using BenchmarkDotNet.Columns;
-
namespace DynamicData.Benchmarks.List;
[MemoryDiagnoser]
@@ -30,7 +24,7 @@ public class ToObservableChangeSet_List
[Arguments(1_000, 1_000)]
public void AddsUpdatesAndFinalization(int itemCount, int sizeLimit)
{
- using var source = new Subject();
+ using var source = new Signal();
using var subscription = source
.ToObservableChangeSet(limitSizeTo: sizeLimit)
diff --git a/src/DynamicData.Benchmarks/Program.cs b/src/DynamicData.Benchmarks/Program.cs
index 5bf5d888f..225fd0ee2 100644
--- a/src/DynamicData.Benchmarks/Program.cs
+++ b/src/DynamicData.Benchmarks/Program.cs
@@ -2,7 +2,6 @@
// Roland Pheasant licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
-using System.IO;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Configs;
diff --git a/src/DynamicData.Reactive.Tests/DynamicData.Reactive.Tests.csproj b/src/DynamicData.Reactive.Tests/DynamicData.Reactive.Tests.csproj
new file mode 100644
index 000000000..fd8e95f88
--- /dev/null
+++ b/src/DynamicData.Reactive.Tests/DynamicData.Reactive.Tests.csproj
@@ -0,0 +1,54 @@
+
+
+ Exe
+ net10.0;net11.0
+ $(DefineConstants);REACTIVE_TESTS
+ $(NoWarn);CS0618;CA1801;CA1812;CA1816;CA1062;CA1063;CS8767;CS8602;CS8618;IDE1006
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DynamicData.Reactive/DynamicData.Reactive.csproj b/src/DynamicData.Reactive/DynamicData.Reactive.csproj
new file mode 100644
index 000000000..30fc1b1f0
--- /dev/null
+++ b/src/DynamicData.Reactive/DynamicData.Reactive.csproj
@@ -0,0 +1,64 @@
+
+
+
+ Dynamic Data
+
+ Bring the power of Rx to collections using Dynamic Data.
+ Dynamic Data is a comprehensive caching and data manipulation solution which introduces domain centric observable collections.
+ Linq extensions enable dynamic filtering, sorting, grouping, transforms, binding, pagination, data virtualisation, expiration, disposal management plus more.
+
+ net462;net472;net48;net481;net8.0;net9.0;net10.0;net11.0
+ true
+ $(DefineConstants);REACTIVE_SHIM
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ObservableCacheEx.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/DynamicData.Tests/API/ApiApprovalTests.DynamicDataReactiveTests.DotNet10_0.verified.txt b/src/DynamicData.Tests/API/ApiApprovalTests.DynamicDataReactiveTests.DotNet10_0.verified.txt
new file mode 100644
index 000000000..7cd598b70
--- /dev/null
+++ b/src/DynamicData.Tests/API/ApiApprovalTests.DynamicDataReactiveTests.DotNet10_0.verified.txt
@@ -0,0 +1,3079 @@
+[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("DynamicData.Benchmarks")]
+[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("DynamicData.Reactive.Tests")]
+[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("DynamicData.Tests")]
+[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName=".NET 10.0")]
+namespace DynamicData.Reactive.Aggregation
+{
+ public readonly struct AggregateItem : System.IEquatable>
+ {
+ public AggregateItem(DynamicData.Reactive.Aggregation.AggregateType Type, TObject Item) { }
+ public TObject Item { get; init; }
+ public DynamicData.Reactive.Aggregation.AggregateType Type { get; init; }
+ public override int GetHashCode() { }
+ }
+ public enum AggregateType
+ {
+ Add = 0,
+ Remove = 1,
+ }
+ public static class AggregationEx
+ {
+ public static System.IObservable> ForAggregation(this System.IObservable> source)
+ where TObject : notnull { }
+ public static System.IObservable> ForAggregation(this System.IObservable> source)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable InvalidateWhen(this System.IObservable source, System.IObservable invalidate) { }
+ public static System.IObservable InvalidateWhen(this System.IObservable source, System.IObservable invalidate) { }
+ }
+ public static class AvgEx
+ {
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0) { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0)
+ where T : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, [System.Runtime.CompilerServices.DecimalConstant(0, 0, 0u, 0u, 0u)] decimal emptyValue)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, double emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, float emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, int emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ public static System.IObservable Avg(this System.IObservable> source, System.Func valueSelector, long emptyValue = 0)
+ where TObject : notnull
+ where TKey : notnull { }
+ }
+ public static class CountEx
+ {
+ public static System.IObservable Count(this System.IObservable> source) { }
+ public static System.IObservable Count(this System.IObservable> source)
+ where TObject : notnull { }
+ public static System.IObservable Count(this System.IObservable> source)
+ where TObject : notnull { }
+ public static System.IObservable Count