namespace System.Linq;
public static class Enumerable
{
public static IEnumerable<(TOuter Outer, TInner Inner)> Join<TOuter, TInner, TKey>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin<TOuter, TInner, TKey>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IEnumerable<(TOuter? Outer, TInner Inner)> RightJoin<TOuter, TInner, TKey>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
}
public static class Queryable
{
public static IQueryable<(TOuter Outer, TInner Inner)> Join<TOuter, TInner, TKey>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IQueryable<(TOuter Outer, TInner? Inner)> LeftJoin<TOuter, TInner, TKey>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IQueryable<(TOuter? Outer, TInner Inner)> RightJoin<TOuter, TInner, TKey>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
}
public static class AsyncEnumerable
{
public static IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector,
Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector,
Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, CancellationToken, ValueTask<TKey>> outerKeySelector,
Func<TInner, CancellationToken, ValueTask<TKey>> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
public static IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin<TOuter, TInner, TKey>(
this IAsyncEnumerable<TOuter> outer,
IAsyncEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
IEqualityComparer<TKey>? comparer = null);
}
Background and motivation
For simplicity of
Joinit should just return(TOuter,TInner)instead of the need forresultSelectorAPI Proposal
API Usage
Alternative Designs
Without this it need to make another lambda just for return tuple
Also since the key might be calculated maybe the return should include key too?
Risks
No response