Repository navigation
Releases: i3arnon/MoreAsyncLINQ
Release list
v3.0.0
What's Changed
- Hide Obsolete overloads in #58
- Tests | Choose in #61
- Tests | Partition in #62
- Generators | Aggregate in #65
- Generators | Cartesian in #67
- Generators | Fold in #69
- Use ArrayPool in #70
Breaking Changes
Obsolete overloads (i.e. ChooseAwait) are no longer extension methods.
Please either:
- Switch to the non-obsolete overloads respecting the new .NET 10.0 async LINQ pattern.
- Use as static method invocation
(MoreAsyncEnumerable.ChooseAwait(..).
Full Changelog: v2.2.0...v3.0.0
v2.2.0
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
v1.0.0
Breaking Changes
Dependency Migration: System.Linq.Async → System.Linq.AsyncEnumerable
This release removes the dependency on System.Linq.Async and replaces it with the new System.Linq.AsyncEnumerable package released in .NET 10.0.
What this means for you:
- If you're upgrading from a previous version, you'll need to update your using directives
- The new
System.Linq.AsyncEnumerableis the official Microsoft implementation shipping with .NET 10 - For more details, see: .NET 10 AsyncEnumerable Breaking Change
IAsyncGrouping → IGrouping in Partition Methods
The following methods now use System.Linq.IGrouping<TKey, TElement> instead of System.Linq.IAsyncGrouping<TKey, TElement>:
PartitionAsync<TSource, TResult>(IAsyncEnumerable<IGrouping<bool, TSource>>, ...)PartitionAsync<TSource, TResult>(IAsyncEnumerable<IGrouping<bool?, TSource>>, ...)PartitionAsync<TKey, TElement, TResult>(IAsyncEnumerable<IGrouping<TKey, TElement>>, ...)PartitionAwaitAsync<TSource, TResult>(IAsyncEnumerable<IGrouping<bool, TSource>>, ...)PartitionAwaitAsync<TSource, TResult>(IAsyncEnumerable<IGrouping<bool?, TSource>>, ...)PartitionAwaitAsync<TKey, TElement, TResult>(IAsyncEnumerable<IGrouping<TKey, TElement>>, ...)
Migration: Update any code that passes IAsyncGrouping to these methods to use IGrouping instead. Since GroupBy in System.Linq.AsyncEnumerable now returns IGrouping, this should be a straightforward change.
Full Changelog: https://github.com/i3arnon/MoreAsyncLINQ/commits/v1.0.0