Repository navigation
v2.0.0
Overview
This release modernizes MoreAsyncLINQ to align with System.Linq.AsyncEnumerable conventions introduced in .NET 10, updates target frameworks, and introduces a consistent API pattern for async delegates.
Breaking Changes
Target Framework Updates
- Changed:
net461→net462 - Added:
net8.0,net9.0,net10.0
PartitionAsync Return Type Changed
PartitionAsync now returns IEnumerable<TSource> instead of IAsyncEnumerable<TSource> in its tuple result:
Before (v1.0.0):
ValueTask<(IAsyncEnumerable<TSource> True, IAsyncEnumerable<TSource> False)> PartitionAsync(...)After (v2.0.0):
ValueTask<(IEnumerable<TSource> True, IEnumerable<TSource> False)> PartitionAsync(...)Migration: Since PartitionAsync is a materializing operator that consumes the entire source sequence, the partition results are now returned as IEnumerable<T>. If you need async enumeration, use ToAsyncEnumerable() on the results.
Async Delegate Signature Changes
All async delegate overloads now require a CancellationToken parameter. The legacy *Await and *AwaitAsync methods that accept Func<T, ValueTask<TResult>> are now marked as [Obsolete].
Before (v1.0.0):
source.SelectAwait(async x => await ProcessAsync(x))After (v2.0.0):
source.Select(async (x, cancellationToken) => await ProcessAsync(x, cancellationToken))This affects all operators with async overloads including:
CartesianChooseExceptByFillBackwardFillForwardFromGenerateByIndexMaxima/MinimaOrderByPad/PadStartPairwisePartitionZipLongest- And many more...
Hidden Operators
The following operators are now hidden (not removed) since they are included in System.Linq.AsyncEnumerable:
CountByDistinctByIndexSkipLastTakeLastToDictionary
These methods remain available for backward compatibility but will not appear in IntelliSense. Prefer using the built-in System.Linq.AsyncEnumerable versions.
Removed ConfigureAwait(false)
Following .NET runtime conventions, ConfigureAwait(false) calls have been removed throughout the library, matching the behavior of System.Linq.AsyncEnumerable.
New Features
Maxima and Minima Operators
New operators that return all maximal/minimal elements with modern async delegate signatures:
// Sync selector
var maxElements = await source.Maxima(x => x.Score).ToListAsync();
// Async selector with CancellationToken
var minElements = await source.Minima(
async (x, ct) => await GetScoreAsync(x, ct),
cancellationToken
).ToListAsync();MaxBy and MinBy continue to work for sync selectors but their *Await variants are now obsolete. Use Maxima and Minima for async scenarios.
Migration Guide
1. Update async delegate calls
Replace legacy async delegates with the new CancellationToken signature:
// Before
items.WhereAwait(async x => await CheckAsync(x))
// After
items.Where(async (x, ct) => await CheckAsync(x, ct))2. Update PartitionAsync usage
If you were iterating the partition results asynchronously:
// Before
var (trueItems, falseItems) = await source.PartitionAsync(predicate);
await foreach (var item in trueItems) { ... }
// After
var (trueItems, falseItems) = await source.PartitionAsync(predicate);
foreach (var item in trueItems) { ... } // Sync iteration
// Or if you need async:
await foreach (var item in trueItems.ToAsyncEnumerable()) { ... }3. Use built-in operators when available
For .NET 10+ projects, prefer the built-in System.Linq.AsyncEnumerable versions of:
CountByDistinctByIndexSkipLastTakeLastToDictionary
Full Changelog: v1.0.0...v2.0.0