diff --git a/src/libraries/System.Linq.AsyncEnumerable/ref/System.Linq.AsyncEnumerable.cs b/src/libraries/System.Linq.AsyncEnumerable/ref/System.Linq.AsyncEnumerable.cs index b13c0504a02459..881b679a19f3ae 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/ref/System.Linq.AsyncEnumerable.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/ref/System.Linq.AsyncEnumerable.cs @@ -73,8 +73,6 @@ public static partial class AsyncEnumerable public static System.Collections.Generic.IAsyncEnumerable GroupBy(this System.Collections.Generic.IAsyncEnumerable source, System.Func keySelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable GroupBy(this System.Collections.Generic.IAsyncEnumerable source, System.Func> keySelector, System.Func> elementSelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable GroupBy(this System.Collections.Generic.IAsyncEnumerable source, System.Func keySelector, System.Func elementSelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable> GroupJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable> GroupJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable GroupJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func, System.Threading.CancellationToken, System.Threading.Tasks.ValueTask> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable GroupJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable<(int Index, TSource Item)> Index(this System.Collections.Generic.IAsyncEnumerable source) { throw null; } @@ -83,8 +81,6 @@ public static partial class AsyncEnumerable public static System.Collections.Generic.IAsyncEnumerable Intersect(this System.Collections.Generic.IAsyncEnumerable first, System.Collections.Generic.IAsyncEnumerable second, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable Join(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable Join(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Threading.Tasks.ValueTask LastAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Func predicate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask LastAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask LastAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -96,8 +92,6 @@ public static partial class AsyncEnumerable public static System.Threading.Tasks.ValueTask LastOrDefaultAsync(this System.Collections.Generic.IAsyncEnumerable source, TSource defaultValue, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Collections.Generic.IAsyncEnumerable LeftJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable LeftJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Threading.Tasks.ValueTask LongCountAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Func predicate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask LongCountAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Func> predicate, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } public static System.Threading.Tasks.ValueTask LongCountAsync(this System.Collections.Generic.IAsyncEnumerable source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } @@ -120,8 +114,6 @@ public static partial class AsyncEnumerable public static System.Collections.Generic.IAsyncEnumerable Reverse(this System.Collections.Generic.IAsyncEnumerable source) { throw null; } public static System.Collections.Generic.IAsyncEnumerable RightJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Func> resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable RightJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func> outerKeySelector, System.Func> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } - public static System.Collections.Generic.IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin(this System.Collections.Generic.IAsyncEnumerable outer, System.Collections.Generic.IAsyncEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IAsyncEnumerable SelectMany(this System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { throw null; } public static System.Collections.Generic.IAsyncEnumerable SelectMany(this System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { throw null; } public static System.Collections.Generic.IAsyncEnumerable SelectMany(this System.Collections.Generic.IAsyncEnumerable source, System.Func> selector) { throw null; } diff --git a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/GroupJoin.cs b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/GroupJoin.cs index f00866f850bfbe..3673aa85956f52 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/GroupJoin.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/GroupJoin.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; @@ -11,120 +10,6 @@ namespace System.Linq { public static partial class AsyncEnumerable { - /// Correlates the elements of two sequences based on key equality and groups the results. If is or omitted, the default equality comparer is used to compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// - /// An that contains elements of type - /// where each grouping contains the outer element as the key and the matching inner elements. - /// - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable> GroupJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() ? Empty>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup lookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - do - { - TOuter item = e.Current; - yield return new AsyncGroupJoinGrouping(item, lookup[outerKeySelector(item)]); - } - while (await e.MoveNextAsync()); - } - } - } - - /// Correlates the elements of two sequences based on key equality and groups the results. If is or omitted, the default equality comparer is used to compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// - /// An that contains elements of type - /// where each grouping contains the outer element as the key and the matching inner elements. - /// - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable> GroupJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() ? Empty>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup lookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - do - { - TOuter item = e.Current; - yield return new AsyncGroupJoinGrouping( - item, - lookup[await outerKeySelector(item, cancellationToken)]); - } - while (await e.MoveNextAsync()); - } - } - } - /// Correlates the elements of two sequences based on key equality and groups the results. /// /// @@ -258,22 +143,4 @@ lookup[await outerKeySelector(item, cancellationToken)], } } } - - internal sealed class AsyncGroupJoinGrouping : IGrouping - { - private readonly TKey _key; - private readonly IEnumerable _elements; - - public AsyncGroupJoinGrouping(TKey key, IEnumerable elements) - { - _key = key; - _elements = elements; - } - - public TKey Key => _key; - - public IEnumerator GetEnumerator() => _elements.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Join.cs b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Join.cs index ba67fe31b7392c..eb086126386a30 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Join.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/Join.cs @@ -156,140 +156,5 @@ static async IAsyncEnumerable Impl( } } } - - /// Correlates the elements of two sequences based on matching keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// - /// An that has elements of type (TOuter Outer, TInner Inner) - /// that are obtained by performing an inner join on two sequences. - /// - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() || inner.IsKnownEmpty() ? Empty<(TOuter Outer, TInner Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter Outer, TInner Inner)> Impl( - IAsyncEnumerable outer, IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup lookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - if (lookup.Count != 0) - { - do - { - TOuter item = e.Current; - Grouping? g = lookup.GetGrouping(outerKeySelector(item), create: false); - if (g is not null) - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } - while (await e.MoveNextAsync()); - } - } - } - } - - /// Correlates the elements of two sequences based on matching keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// - /// An that has elements of type (TOuter Outer, TInner Inner) - /// that are obtained by performing an inner join on two sequences. - /// - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter Outer, TInner Inner)> Join( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() || inner.IsKnownEmpty() ? Empty<(TOuter Outer, TInner Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter Outer, TInner Inner)> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup lookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - if (lookup.Count != 0) - { - do - { - TOuter item = e.Current; - Grouping? g = lookup.GetGrouping(await outerKeySelector(item, cancellationToken), create: false); - if (g is not null) - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } - while (await e.MoveNextAsync()); - } - } - } - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/LeftJoin.cs b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/LeftJoin.cs index 8438bdaac6963f..a86645ece88d69 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/LeftJoin.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/LeftJoin.cs @@ -152,136 +152,5 @@ static async IAsyncEnumerable Impl( } } } - - /// Correlates the elements of two sequences based on matching keys. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner? Inner) that are obtained by performing a left outer join on two sequences. - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() ? Empty<(TOuter Outer, TInner? Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter Outer, TInner? Inner)> Impl( - IAsyncEnumerable outer, IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup innerLookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - do - { - TOuter item = e.Current; - Grouping? g = innerLookup.GetGrouping(outerKeySelector(item), create: false); - if (g is null) - { - yield return (item, default); - } - else - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } - while (await e.MoveNextAsync()); - } - } - } - - /// Correlates the elements of two sequences based on matching keys. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner? Inner) that are obtained by performing a left outer join on two sequences. - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - outer.IsKnownEmpty() ? Empty<(TOuter Outer, TInner? Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter Outer, TInner? Inner)> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = outer.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup innerLookup = await AsyncLookup.CreateForJoinAsync(inner, innerKeySelector, comparer, cancellationToken); - do - { - TOuter item = e.Current; - Grouping? g = innerLookup.GetGrouping(await outerKeySelector(item, cancellationToken), create: false); - if (g is null) - { - yield return (item, default); - } - else - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } - while (await e.MoveNextAsync()); - } - } - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/RightJoin.cs b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/RightJoin.cs index 6e83ddccad533c..9328acb4597abc 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/RightJoin.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/src/System/Linq/RightJoin.cs @@ -153,137 +153,5 @@ static async IAsyncEnumerable Impl( } } } - - /// Correlates the elements of two sequences based on matching keys. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter? Outer, TInner Inner) that are obtained by performing a right outer join on two sequences. - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - inner.IsKnownEmpty() ? Empty<(TOuter? Outer, TInner Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter? Outer, TInner Inner)> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = inner.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup outerLookup = await AsyncLookup.CreateForJoinAsync(outer, outerKeySelector, comparer, cancellationToken); - do - { - TInner item = e.Current; - Grouping? g = outerLookup.GetGrouping(innerKeySelector(item), create: false); - if (g is null) - { - yield return (default, item); - } - else - { - int count = g._count; - TOuter[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (elements[i], item); - } - } - } - while (await e.MoveNextAsync()); - } - } - } - - /// Correlates the elements of two sequences based on matching keys. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to use to hash and compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter? Outer, TInner Inner) that are obtained by performing a right outer join on two sequences. - /// is . - /// is . - /// is . - /// is . - public static IAsyncEnumerable<(TOuter? Outer, TInner Inner)> RightJoin( - this IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return - inner.IsKnownEmpty() ? Empty<(TOuter? Outer, TInner Inner)>() : - Impl(outer, inner, outerKeySelector, innerKeySelector, comparer, default); - - static async IAsyncEnumerable<(TOuter? Outer, TInner Inner)> Impl( - IAsyncEnumerable outer, - IAsyncEnumerable inner, - Func> outerKeySelector, - Func> innerKeySelector, - IEqualityComparer? comparer, - [EnumeratorCancellation] CancellationToken cancellationToken) - { - await using IAsyncEnumerator e = inner.GetAsyncEnumerator(cancellationToken); - - if (await e.MoveNextAsync()) - { - AsyncLookup outerLookup = await AsyncLookup.CreateForJoinAsync(outer, outerKeySelector, comparer, cancellationToken); - do - { - TInner item = e.Current; - Grouping? g = outerLookup.GetGrouping(await innerKeySelector(item, cancellationToken), create: false); - if (g is null) - { - yield return (default, item); - } - else - { - int count = g._count; - TOuter[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (elements[i], item); - } - } - } - while (await e.MoveNextAsync()); - } - } - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/tests/GroupJoinTests.cs b/src/libraries/System.Linq.AsyncEnumerable/tests/GroupJoinTests.cs index c09a68c9482822..305faf3c77681f 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/tests/GroupJoinTests.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/tests/GroupJoinTests.cs @@ -26,20 +26,6 @@ public void InvalidInputs_Throws() AssertExtensions.Throws("resultSelector", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), async (outer, ct) => outer, async (inner, ct) => inner, (Func, CancellationToken, ValueTask>)null)); } - [Fact] - public void InvalidInputs_WithoutResultSelector_Throws() - { - AssertExtensions.Throws("outer", () => AsyncEnumerable.GroupJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), outer => outer, inner => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, outer => outer, inner => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func)null, inner => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), outer => outer, (Func)null)); - - AssertExtensions.Throws("outer", () => AsyncEnumerable.GroupJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func>)null, async (inner, ct) => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.GroupJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), async (outer, ct) => outer, (Func>)null)); - } - [Fact] public void Empty_ProducesEmpty() // validating an optimization / implementation detail { @@ -47,13 +33,6 @@ public void Empty_ProducesEmpty() // validating an optimization / implementation Assert.Same(AsyncEnumerable.Empty(), AsyncEnumerable.Empty().GroupJoin(CreateSource(1, 2, 3), async (s, ct) => s, async (i, ct) => i.ToString(), async (s, e, ct) => s)); } - [Fact] - public void Empty_WithoutResultSelector_ProducesEmpty() - { - Assert.Same(AsyncEnumerable.Empty>(), AsyncEnumerable.Empty().GroupJoin(CreateSource(1, 2, 3), s => s, i => i.ToString())); - Assert.Same(AsyncEnumerable.Empty>(), AsyncEnumerable.Empty().GroupJoin(CreateSource(1, 2, 3), async (s, ct) => s, async (i, ct) => i.ToString())); - } - [Fact] public async Task VariousValues_MatchesEnumerable_String() { @@ -76,38 +55,6 @@ await AssertEqual( } } - [Fact] - public async Task VariousValues_WithoutResultSelector_MatchesEnumerable() - { - int[] outer = [1, 2, 3]; - int[] inner = [1, 2, 2, 3, 3, 3]; - - foreach (IAsyncEnumerable outerSource in CreateSources(outer)) - foreach (IAsyncEnumerable innerSource in CreateSources(inner)) - { -#if NET - var expected = outer.GroupJoin(inner, o => o, i => i); - var result = await outerSource.GroupJoin(innerSource, o => o, i => i).ToListAsync(); - - Assert.Equal(expected.Count(), result.Count); - foreach (var (exp, act) in expected.Zip(result)) - { - Assert.Equal(exp.Key, act.Key); - Assert.Equal(exp.ToList(), act.ToList()); - } - - var resultAsync = await outerSource.GroupJoin(innerSource, async (o, ct) => o, async (i, ct) => i).ToListAsync(); - - Assert.Equal(expected.Count(), resultAsync.Count); - foreach (var (exp, act) in expected.Zip(resultAsync)) - { - Assert.Equal(exp.Key, act.Key); - Assert.Equal(exp.ToList(), act.ToList()); - } -#endif - } - } - [Fact] public async Task Cancellation_Cancels() { @@ -220,31 +167,5 @@ public async Task InterfaceCalls_ExpectedCounts() Assert.Equal(4, inner.CurrentCount); Assert.Equal(1, inner.DisposeAsyncCount); } - - [Fact] - public async Task InterfaceCalls_WithoutResultSelector_ExpectedCounts() - { - TrackingAsyncEnumerable outer, inner; - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.GroupJoin(inner, outer => outer, inner => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.GroupJoin(inner, async (outer, ct) => outer, async (inner, ct) => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/tests/JoinTests.cs b/src/libraries/System.Linq.AsyncEnumerable/tests/JoinTests.cs index d84c6cf05f7f2d..258ea44c57ba49 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/tests/JoinTests.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/tests/JoinTests.cs @@ -176,83 +176,5 @@ public async Task InterfaceCalls_ExpectedCounts() Assert.Equal(4, inner.CurrentCount); Assert.Equal(1, inner.DisposeAsyncCount); } - - [Fact] - public void TupleJoin_InvalidInputs_Throws() - { - AssertExtensions.Throws("outer", () => AsyncEnumerable.Join((IAsyncEnumerable)null, AsyncEnumerable.Empty(), outer => outer, inner => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, outer => outer, inner => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func)null, inner => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), outer => outer, (Func)null)); - - AssertExtensions.Throws("outer", () => AsyncEnumerable.Join((IAsyncEnumerable)null, AsyncEnumerable.Empty(), async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func>)null, async (inner, ct) => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.Join(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), async (outer, ct) => outer, (Func>)null)); - } - - [Fact] - public void TupleJoin_Empty_ProducesEmpty() - { - IAsyncEnumerable empty = AsyncEnumerable.Empty(); - IAsyncEnumerable nonEmpty = CreateSource("1", "2", "3"); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.Join(empty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.Join(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.Join(empty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.Join(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.Join(nonEmpty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.Join(nonEmpty, async (s, ct) => s, async (s, ct) => s)); - } - - [Fact] - public async Task TupleJoin_VariousValues_MatchesEnumerable_String() - { - Random rand = new(42); - foreach (int length in new[] { 0, 1, 2, 1000 }) - { - string[] values = new string[length]; - FillRandom(rand, values); - - foreach (IAsyncEnumerable source in CreateSources(values)) - { - await AssertEqual( - values.Join(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.Join(source, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - - await AssertEqual( - values.Join(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.Join(source, async (s, ct) => s.Length > 0 ? s[0] : ' ', async (s, ct) => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - } - } - } - - [Fact] - public async Task TupleJoin_InterfaceCalls_ExpectedCounts() - { - TrackingAsyncEnumerable outer, inner; - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.Join(inner, outer => outer, inner => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.Join(inner, async (outer, ct) => outer, async (inner, ct) => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/tests/LeftJoinTests.cs b/src/libraries/System.Linq.AsyncEnumerable/tests/LeftJoinTests.cs index 917371e9ebe958..759ae3ab1ed1d8 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/tests/LeftJoinTests.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/tests/LeftJoinTests.cs @@ -178,85 +178,5 @@ public async Task InterfaceCalls_ExpectedCounts() Assert.Equal(4, inner.CurrentCount); Assert.Equal(1, inner.DisposeAsyncCount); } - - [Fact] - public void TupleLeftJoin_InvalidInputs_Throws() - { - AssertExtensions.Throws("outer", () => AsyncEnumerable.LeftJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), outer => outer, inner => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, outer => outer, inner => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func)null, inner => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), outer => outer, (Func)null)); - - AssertExtensions.Throws("outer", () => AsyncEnumerable.LeftJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func>)null, async (inner, ct) => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.LeftJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), async (outer, ct) => outer, (Func>)null)); - } - - [Fact] - public void TupleLeftJoin_Empty_ProducesEmpty() - { - IAsyncEnumerable empty = AsyncEnumerable.Empty(); - IAsyncEnumerable nonEmpty = CreateSource("1", "2", "3"); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.LeftJoin(empty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.LeftJoin(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.NotSame(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.LeftJoin(empty, s => s, s => s)); - Assert.NotSame(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.LeftJoin(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.LeftJoin(nonEmpty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.LeftJoin(nonEmpty, async (s, ct) => s, async (s, ct) => s)); - } - -#if NET - [Fact] - public async Task TupleLeftJoin_VariousValues_MatchesEnumerable_String() - { - Random rand = new(42); - foreach (int length in new[] { 0, 1, 2, 1000 }) - { - string[] values = new string[length]; - FillRandom(rand, values); - - foreach (IAsyncEnumerable source in CreateSources(values)) - { - await AssertEqual( - values.LeftJoin(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.LeftJoin(source, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - - await AssertEqual( - values.LeftJoin(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.LeftJoin(source, async (s, ct) => s.Length > 0 ? s[0] : ' ', async (s, ct) => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - } - } - } -#endif - - [Fact] - public async Task TupleLeftJoin_InterfaceCalls_ExpectedCounts() - { - TrackingAsyncEnumerable outer, inner; - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.LeftJoin(inner, outer => outer, inner => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.LeftJoin(inner, async (outer, ct) => outer, async (inner, ct) => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - } } } diff --git a/src/libraries/System.Linq.AsyncEnumerable/tests/RightJoinTests.cs b/src/libraries/System.Linq.AsyncEnumerable/tests/RightJoinTests.cs index de91b6201c4403..e7f123a464e463 100644 --- a/src/libraries/System.Linq.AsyncEnumerable/tests/RightJoinTests.cs +++ b/src/libraries/System.Linq.AsyncEnumerable/tests/RightJoinTests.cs @@ -178,85 +178,5 @@ public async Task InterfaceCalls_ExpectedCounts() Assert.Equal(4, inner.CurrentCount); Assert.Equal(1, inner.DisposeAsyncCount); } - - [Fact] - public void TupleRightJoin_InvalidInputs_Throws() - { - AssertExtensions.Throws("outer", () => AsyncEnumerable.RightJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), outer => outer, inner => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, outer => outer, inner => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func)null, inner => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), outer => outer, (Func)null)); - - AssertExtensions.Throws("outer", () => AsyncEnumerable.RightJoin((IAsyncEnumerable)null, AsyncEnumerable.Empty(), async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("inner", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), (IAsyncEnumerable)null, async (outer, ct) => outer, async (inner, ct) => inner)); - AssertExtensions.Throws("outerKeySelector", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), (Func>)null, async (inner, ct) => inner)); - AssertExtensions.Throws("innerKeySelector", () => AsyncEnumerable.RightJoin(AsyncEnumerable.Empty(), AsyncEnumerable.Empty(), async (outer, ct) => outer, (Func>)null)); - } - - [Fact] - public void TupleRightJoin_Empty_ProducesEmpty() - { - IAsyncEnumerable empty = AsyncEnumerable.Empty(); - IAsyncEnumerable nonEmpty = CreateSource("1", "2", "3"); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.RightJoin(empty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), empty.RightJoin(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.RightJoin(empty, s => s, s => s)); - Assert.Same(AsyncEnumerable.Empty<(string, string)>(), nonEmpty.RightJoin(empty, async (s, ct) => s, async (s, ct) => s)); - - Assert.NotSame(AsyncEnumerable.Empty<(string, string)>(), empty.RightJoin(nonEmpty, s => s, s => s)); - Assert.NotSame(AsyncEnumerable.Empty<(string, string)>(), empty.RightJoin(nonEmpty, async (s, ct) => s, async (s, ct) => s)); - } - -#if NET - [Fact] - public async Task TupleRightJoin_VariousValues_MatchesEnumerable_String() - { - Random rand = new(42); - foreach (int length in new[] { 0, 1, 2, 1000 }) - { - string[] values = new string[length]; - FillRandom(rand, values); - - foreach (IAsyncEnumerable source in CreateSources(values)) - { - await AssertEqual( - values.RightJoin(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.RightJoin(source, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - - await AssertEqual( - values.RightJoin(values, s => s.Length > 0 ? s[0] : ' ', s => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner), - source.RightJoin(source, async (s, ct) => s.Length > 0 ? s[0] : ' ', async (s, ct) => s.Length > 1 ? s[1] : ' ').Select(t => t.Outer + t.Inner)); - } - } - } -#endif - - [Fact] - public async Task TupleRightJoin_InterfaceCalls_ExpectedCounts() - { - TrackingAsyncEnumerable outer, inner; - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.RightJoin(inner, outer => outer, inner => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - - outer = CreateSource(2, 4, 8, 16).Track(); - inner = CreateSource(1, 2, 3, 4).Track(); - await ConsumeAsync(outer.RightJoin(inner, async (outer, ct) => outer, async (inner, ct) => inner)); - Assert.Equal(5, outer.MoveNextAsyncCount); - Assert.Equal(4, outer.CurrentCount); - Assert.Equal(1, outer.DisposeAsyncCount); - Assert.Equal(5, inner.MoveNextAsyncCount); - Assert.Equal(4, inner.CurrentCount); - Assert.Equal(1, inner.DisposeAsyncCount); - } } } diff --git a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs index 82d85662557874..2d63b858f0bd26 100644 --- a/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs +++ b/src/libraries/System.Linq.Queryable/ref/System.Linq.Queryable.cs @@ -108,7 +108,6 @@ public static partial class Queryable public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; } public static System.Linq.IQueryable GroupBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Linq.Expressions.Expression> elementSelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Linq.IQueryable> GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector) { throw null; } public static System.Linq.IQueryable GroupJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression, TResult>> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Linq.IQueryable<(int Index, TSource Item)> Index(this System.Linq.IQueryable source) { throw null; } @@ -118,7 +117,6 @@ public static partial class Queryable public static System.Linq.IQueryable Intersect(this System.Linq.IQueryable source1, System.Collections.Generic.IEnumerable source2, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Linq.IQueryable Join(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } public static System.Linq.IQueryable Join(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Linq.IQueryable<(TOuter Outer, TInner Inner)> Join(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static TSource? LastOrDefault(this System.Linq.IQueryable source) { throw null; } public static TSource? LastOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } public static TSource LastOrDefault(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate, TSource defaultValue) { throw null; } @@ -127,7 +125,6 @@ public static partial class Queryable public static TSource Last(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } public static System.Linq.IQueryable LeftJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } public static System.Linq.IQueryable LeftJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Linq.IQueryable<(TOuter Outer, TInner? Inner)> LeftJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static long LongCount(this System.Linq.IQueryable source) { throw null; } public static long LongCount(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> predicate) { throw null; } public static TSource? MaxBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) { throw null; } @@ -161,7 +158,6 @@ public static partial class Queryable public static System.Linq.IQueryable Reverse(this System.Linq.IQueryable source) { throw null; } public static System.Linq.IQueryable RightJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } public static System.Linq.IQueryable RightJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Linq.Expressions.Expression> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Linq.IQueryable<(TOuter? Outer, TInner Inner)> RightJoin(this System.Linq.IQueryable outer, System.Collections.Generic.IEnumerable inner, System.Linq.Expressions.Expression> outerKeySelector, System.Linq.Expressions.Expression> innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> selector) { throw null; } public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> selector) { throw null; } public static System.Linq.IQueryable SelectMany(this System.Linq.IQueryable source, System.Linq.Expressions.Expression>> collectionSelector, System.Linq.Expressions.Expression> resultSelector) { throw null; } diff --git a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs index 09243d4c8431ac..1290b8f6819e23 100644 --- a/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/src/System/Linq/Queryable.cs @@ -408,66 +408,6 @@ public static IQueryable Join(this IQuer outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Quote(resultSelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); } - /// Correlates the elements of two sequences based on key equality and groups the results. If is or omitted, the default equality comparer is used to compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// - /// An that contains elements of type - /// where each grouping contains the outer element as the key and the matching inner elements. - /// - /// is . - /// is . - /// is . - /// is . - [DynamicDependency("GroupJoin`3", typeof(Enumerable))] - public static IQueryable> GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return outer.Provider.CreateQuery>( - Expression.Call( - null, - new Func, IEnumerable, Expression>, Expression>, IEqualityComparer, IQueryable>>(GroupJoin).Method, - outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); - } - - /// - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner Inner) that are obtained by performing an inner join on two sequences. - /// or or or is . - [DynamicDependency("Join`3", typeof(Enumerable))] - public static IQueryable<(TOuter Outer, TInner Inner)> Join(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return outer.Provider.CreateQuery<(TOuter Outer, TInner Inner)>( - Expression.Call( - null, - new Func, IEnumerable, Expression>, Expression>, IEqualityComparer, IQueryable<(TOuter Outer, TInner Inner)>>(Join).Method, - outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); - } - [DynamicDependency("GroupJoin`4", typeof(Enumerable))] public static IQueryable GroupJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, Expression, TResult>> resultSelector) { @@ -729,34 +669,6 @@ public static IQueryable LeftJoin(this I outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Quote(resultSelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); } - /// - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner? Inner) that are obtained by performing a left outer join on two sequences. - /// or or or is . - [DynamicDependency("LeftJoin`3", typeof(Enumerable))] - public static IQueryable<(TOuter Outer, TInner? Inner)> LeftJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return outer.Provider.CreateQuery<(TOuter Outer, TInner? Inner)>( - Expression.Call( - null, - new Func, IEnumerable, Expression>, Expression>, IEqualityComparer, IQueryable<(TOuter Outer, TInner? Inner)>>(LeftJoin).Method, - outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); - } - /// /// Sorts the elements of a sequence in ascending order. /// @@ -1182,34 +1094,6 @@ public static IQueryable RightJoin(this outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Quote(resultSelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); } - /// - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter? Outer, TInner Inner) that are obtained by performing a right outer join on two sequences. - /// or or or is . - [DynamicDependency("RightJoin`3", typeof(Enumerable))] - public static IQueryable<(TOuter? Outer, TInner Inner)> RightJoin(this IQueryable outer, IEnumerable inner, Expression> outerKeySelector, Expression> innerKeySelector, IEqualityComparer? comparer = null) - { - ArgumentNullException.ThrowIfNull(outer); - ArgumentNullException.ThrowIfNull(inner); - ArgumentNullException.ThrowIfNull(outerKeySelector); - ArgumentNullException.ThrowIfNull(innerKeySelector); - - return outer.Provider.CreateQuery<(TOuter? Outer, TInner Inner)>( - Expression.Call( - null, - new Func, IEnumerable, Expression>, Expression>, IEqualityComparer, IQueryable<(TOuter? Outer, TInner Inner)>>(RightJoin).Method, - outer.Expression, GetSourceExpression(inner), Expression.Quote(outerKeySelector), Expression.Quote(innerKeySelector), Expression.Constant(comparer, typeof(IEqualityComparer)))); - } - [DynamicDependency("ThenBy`2", typeof(Enumerable))] public static IOrderedQueryable ThenBy(this IOrderedQueryable source, Expression> keySelector) { diff --git a/src/libraries/System.Linq.Queryable/tests/GroupJoinTests.cs b/src/libraries/System.Linq.Queryable/tests/GroupJoinTests.cs index 8d79f7e1c17919..3db5cb8cad203e 100644 --- a/src/libraries/System.Linq.Queryable/tests/GroupJoinTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/GroupJoinTests.cs @@ -287,67 +287,5 @@ public void GroupJoin2() var count = new[] { 0, 1, 2 }.AsQueryable().GroupJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, (n1, n2) => n1, EqualityComparer.Default).Count(); Assert.Equal(3, count); } - - [Fact] - public void GroupJoinWithoutResultSelector() - { - var result = new[] { 0, 1, 2 }.AsQueryable().GroupJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2).ToList(); - Assert.Equal(3, result.Count); - Assert.Equal(0, result[0].Key); - Assert.Empty(result[0]); - Assert.Equal(1, result[1].Key); - Assert.Single(result[1]); - Assert.Equal(2, result[2].Key); - Assert.Single(result[2]); - } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterNull() - { - IQueryable outer = null; - int[] inner = { 1, 2, 3 }; - - AssertExtensions.Throws("outer", () => outer.GroupJoin(inner.AsQueryable(), n1 => n1, n2 => n2)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_InnerNull() - { - int[] outer = { 0, 1, 2 }; - IQueryable inner = null; - - AssertExtensions.Throws("inner", () => outer.AsQueryable().GroupJoin(inner, n1 => n1, n2 => n2)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterKeySelectorNull() - { - int[] outer = { 0, 1, 2 }; - int[] inner = { 1, 2, 3 }; - - AssertExtensions.Throws("outerKeySelector", () => outer.AsQueryable().GroupJoin(inner.AsQueryable(), null, n2 => n2)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_InnerKeySelectorNull() - { - int[] outer = { 0, 1, 2 }; - int[] inner = { 1, 2, 3 }; - - AssertExtensions.Throws("innerKeySelector", () => outer.AsQueryable().GroupJoin(inner.AsQueryable(), n1 => n1, null)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_CustomComparer() - { - var result = new[] { "Tim", "Bob", "Robert" }.AsQueryable().GroupJoin(new[] { "miT", "Robert" }, n1 => n1, n2 => n2, new AnagramEqualityComparer()).ToList(); - Assert.Equal(3, result.Count); - Assert.Equal("Tim", result[0].Key); - Assert.Single(result[0]); - Assert.Equal("Bob", result[1].Key); - Assert.Empty(result[1]); - Assert.Equal("Robert", result[2].Key); - Assert.Single(result[2]); - } } } diff --git a/src/libraries/System.Linq.Queryable/tests/JoinTests.cs b/src/libraries/System.Linq.Queryable/tests/JoinTests.cs index 0b0b9c536c1ecc..2677a404871d98 100644 --- a/src/libraries/System.Linq.Queryable/tests/JoinTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/JoinTests.cs @@ -262,95 +262,5 @@ public void Join2() var count = new[] { 0, 1, 2 }.AsQueryable().Join(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, (n1, n2) => n1 + n2, EqualityComparer.Default).Count(); Assert.Equal(2, count); } - - [Fact] - public void TupleJoin_Basic() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 }, - new CustomerRec{ name = "Robert", custID = 99022 } - }; - OrderRec[] inner = { - new OrderRec{ orderID = 45321, custID = 99022, total = 50 }, - new OrderRec{ orderID = 43421, custID = 29022, total = 20 }, - new OrderRec{ orderID = 95421, custID = 98022, total = 9 } - }; - - var result = outer.AsQueryable().Join(inner.AsQueryable(), e => e.custID, e => e.custID).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.orderID == 95421); - Assert.Contains(result, r => r.Outer.name == "Robert" && r.Inner.orderID == 45321); - } - - [Fact] - public void TupleJoin_WithComparer() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 } - }; - AnagramRec[] inner = { - new AnagramRec{ name = "miT", orderID = 43455, total = 10 }, - new AnagramRec{ name = "Prakash", orderID = 323232, total = 9 } - }; - - var result = outer.AsQueryable().Join(inner.AsQueryable(), e => e.name, e => e.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.name == "Prakash"); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - } - - [Fact] - public void TupleJoin_OuterNull() - { - IQueryable outer = null; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outer", () => outer.Join(inner.AsQueryable(), e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleJoin_InnerNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - IEnumerable inner = null; - - AssertExtensions.Throws("inner", () => outer.AsQueryable().Join(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outerKeySelector", () => outer.AsQueryable().Join(inner.AsQueryable(), (Expression>)null, e => e.custID)); - } - - [Fact] - public void TupleJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("innerKeySelector", () => outer.AsQueryable().Join(inner.AsQueryable(), e => e.custID, (Expression>)null)); - } - - [Fact] - public void TupleJoin1() - { - var count = new[] { 0, 1, 2 }.AsQueryable().Join(new[] { 1, 2, 3 }, n1 => n1, n2 => n2).Count(); - Assert.Equal(2, count); - } - - [Fact] - public void TupleJoin2() - { - var count = new[] { 0, 1, 2 }.AsQueryable().Join(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, EqualityComparer.Default).Count(); - Assert.Equal(2, count); - } } } diff --git a/src/libraries/System.Linq.Queryable/tests/LeftJoinTests.cs b/src/libraries/System.Linq.Queryable/tests/LeftJoinTests.cs index 7d8b2d6282944e..9666a1c7c8bb29 100644 --- a/src/libraries/System.Linq.Queryable/tests/LeftJoinTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/LeftJoinTests.cs @@ -270,95 +270,5 @@ public void Join2() var count = new[] { 0, 1, 2 }.AsQueryable().LeftJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, (n1, n2) => n1 + n2, EqualityComparer.Default).Count(); Assert.Equal(3, count); } - - [Fact] - public void TupleLeftJoin_Basic() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 }, - new CustomerRec{ name = "Robert", custID = 99022 } - }; - OrderRec[] inner = { - new OrderRec{ orderID = 45321, custID = 99022, total = 50 }, - new OrderRec{ orderID = 43421, custID = 29022, total = 20 }, - new OrderRec{ orderID = 95421, custID = 98022, total = 9 } - }; - - var result = outer.AsQueryable().LeftJoin(inner.AsQueryable(), e => e.custID, e => e.custID).ToList(); - - Assert.Equal(3, result.Count); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.orderID == 95421); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.orderID == 0); - Assert.Contains(result, r => r.Outer.name == "Robert" && r.Inner.orderID == 45321); - } - - [Fact] - public void TupleLeftJoin_WithComparer() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 } - }; - AnagramRec[] inner = { - new AnagramRec{ name = "miT", orderID = 43455, total = 10 } - }; - - var result = outer.AsQueryable().LeftJoin(inner.AsQueryable(), e => e.name, e => e.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.name == null); - } - - [Fact] - public void TupleLeftJoin_OuterNull() - { - IQueryable outer = null; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outer", () => outer.LeftJoin(inner.AsQueryable(), e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleLeftJoin_InnerNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - IEnumerable inner = null; - - AssertExtensions.Throws("inner", () => outer.AsQueryable().LeftJoin(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleLeftJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outerKeySelector", () => outer.AsQueryable().LeftJoin(inner.AsQueryable(), (Expression>)null, e => e.custID)); - } - - [Fact] - public void TupleLeftJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("innerKeySelector", () => outer.AsQueryable().LeftJoin(inner.AsQueryable(), e => e.custID, (Expression>)null)); - } - - [Fact] - public void TupleLeftJoin1() - { - var count = new[] { 0, 1, 2 }.AsQueryable().LeftJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2).Count(); - Assert.Equal(3, count); - } - - [Fact] - public void TupleLeftJoin2() - { - var count = new[] { 0, 1, 2 }.AsQueryable().LeftJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, EqualityComparer.Default).Count(); - Assert.Equal(3, count); - } } } diff --git a/src/libraries/System.Linq.Queryable/tests/RightJoinTests.cs b/src/libraries/System.Linq.Queryable/tests/RightJoinTests.cs index de0120176d6f20..4ca4930a350edf 100644 --- a/src/libraries/System.Linq.Queryable/tests/RightJoinTests.cs +++ b/src/libraries/System.Linq.Queryable/tests/RightJoinTests.cs @@ -269,95 +269,5 @@ public void Join2() var count = new[] { 0, 1, 2 }.AsQueryable().RightJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, (n1, n2) => n1 + n2, EqualityComparer.Default).Count(); Assert.Equal(3, count); } - - [Fact] - public void TupleRightJoin_Basic() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 }, - new CustomerRec{ name = "Robert", custID = 99022 } - }; - OrderRec[] inner = { - new OrderRec{ orderID = 45321, custID = 99022, total = 50 }, - new OrderRec{ orderID = 43421, custID = 29022, total = 20 }, - new OrderRec{ orderID = 95421, custID = 98022, total = 9 } - }; - - var result = outer.AsQueryable().RightJoin(inner.AsQueryable(), e => e.custID, e => e.custID).ToList(); - - Assert.Equal(3, result.Count); - Assert.Contains(result, r => r.Outer.name == "Robert" && r.Inner.orderID == 45321); - Assert.Contains(result, r => r.Outer.name == null && r.Inner.orderID == 43421); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.orderID == 95421); - } - - [Fact] - public void TupleRightJoin_WithComparer() - { - CustomerRec[] outer = { - new CustomerRec{ name = "Tim", custID = 99021 } - }; - AnagramRec[] inner = { - new AnagramRec{ name = "miT", orderID = 43455, total = 10 }, - new AnagramRec{ name = "Prakash", orderID = 323232, total = 9 } - }; - - var result = outer.AsQueryable().RightJoin(inner.AsQueryable(), e => e.name, e => e.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - Assert.Contains(result, r => r.Outer.name == null && r.Inner.name == "Prakash"); - } - - [Fact] - public void TupleRightJoin_OuterNull() - { - IQueryable outer = null; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outer", () => outer.RightJoin(inner.AsQueryable(), e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleRightJoin_InnerNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - IEnumerable inner = null; - - AssertExtensions.Throws("inner", () => outer.AsQueryable().RightJoin(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void TupleRightJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("outerKeySelector", () => outer.AsQueryable().RightJoin(inner.AsQueryable(), (Expression>)null, e => e.custID)); - } - - [Fact] - public void TupleRightJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = { new CustomerRec{ name = "Prakash", custID = 98022 } }; - OrderRec[] inner = { new OrderRec{ orderID = 45321, custID = 98022, total = 50 } }; - - AssertExtensions.Throws("innerKeySelector", () => outer.AsQueryable().RightJoin(inner.AsQueryable(), e => e.custID, (Expression>)null)); - } - - [Fact] - public void TupleRightJoin1() - { - var count = new[] { 0, 1, 2 }.AsQueryable().RightJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2).Count(); - Assert.Equal(3, count); - } - - [Fact] - public void TupleRightJoin2() - { - var count = new[] { 0, 1, 2 }.AsQueryable().RightJoin(new[] { 1, 2, 3 }, n1 => n1, n2 => n2, EqualityComparer.Default).Count(); - Assert.Equal(3, count); - } } } diff --git a/src/libraries/System.Linq/ref/System.Linq.cs b/src/libraries/System.Linq/ref/System.Linq.cs index 8451e05ac4fab6..0c2d82b2111766 100644 --- a/src/libraries/System.Linq/ref/System.Linq.cs +++ b/src/libraries/System.Linq/ref/System.Linq.cs @@ -81,7 +81,6 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable GroupBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Collections.Generic.IEnumerable GroupBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Func elementSelector, System.Func, TResult> resultSelector) { throw null; } public static System.Collections.Generic.IEnumerable GroupBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Func elementSelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Collections.Generic.IEnumerable> GroupJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IEnumerable GroupJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func, TResult> resultSelector) { throw null; } public static System.Collections.Generic.IEnumerable GroupJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func, TResult> resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Collections.Generic.IEnumerable<(int Index, TSource Item)> Index(this System.Collections.Generic.IEnumerable source) { throw null; } @@ -92,7 +91,6 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable Intersect(this System.Collections.Generic.IEnumerable first, System.Collections.Generic.IEnumerable second, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } public static System.Collections.Generic.IEnumerable Join(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector) { throw null; } public static System.Collections.Generic.IEnumerable Join(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Collections.Generic.IEnumerable<(TOuter Outer, TInner Inner)> Join(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static TSource? LastOrDefault(this System.Collections.Generic.IEnumerable source) { throw null; } public static TSource LastOrDefault(this System.Collections.Generic.IEnumerable source, TSource defaultValue) { throw null; } public static TSource? LastOrDefault(this System.Collections.Generic.IEnumerable source, System.Func predicate) { throw null; } @@ -101,7 +99,6 @@ public static System.Collections.Generic.IEnumerable< public static TSource Last(this System.Collections.Generic.IEnumerable source, System.Func predicate) { throw null; } public static System.Collections.Generic.IEnumerable LeftJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector) { throw null; } public static System.Collections.Generic.IEnumerable LeftJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Collections.Generic.IEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static long LongCount(this System.Collections.Generic.IEnumerable source) { throw null; } public static long LongCount(this System.Collections.Generic.IEnumerable source, System.Func predicate) { throw null; } public static decimal Max(this System.Collections.Generic.IEnumerable source) { throw null; } @@ -170,7 +167,6 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable Reverse(this TSource[] source) { throw null; } public static System.Collections.Generic.IEnumerable RightJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector) { throw null; } public static System.Collections.Generic.IEnumerable RightJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Func resultSelector, System.Collections.Generic.IEqualityComparer? comparer) { throw null; } - public static System.Collections.Generic.IEnumerable<(TOuter? Outer, TInner Inner)> RightJoin(this System.Collections.Generic.IEnumerable outer, System.Collections.Generic.IEnumerable inner, System.Func outerKeySelector, System.Func innerKeySelector, System.Collections.Generic.IEqualityComparer? comparer = null) { throw null; } public static System.Collections.Generic.IEnumerable SelectMany(this System.Collections.Generic.IEnumerable source, System.Func> selector) { throw null; } public static System.Collections.Generic.IEnumerable SelectMany(this System.Collections.Generic.IEnumerable source, System.Func> selector) { throw null; } public static System.Collections.Generic.IEnumerable SelectMany(this System.Collections.Generic.IEnumerable source, System.Func> collectionSelector, System.Func resultSelector) { throw null; } diff --git a/src/libraries/System.Linq/src/System/Linq/GroupJoin.cs b/src/libraries/System.Linq/src/System/Linq/GroupJoin.cs index 0fefce7dfc842e..b59ca859ec568c 100644 --- a/src/libraries/System.Linq/src/System/Linq/GroupJoin.cs +++ b/src/libraries/System.Linq/src/System/Linq/GroupJoin.cs @@ -1,60 +1,12 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections; using System.Collections.Generic; namespace System.Linq { public static partial class Enumerable { - /// Correlates the elements of two sequences based on key equality and groups the results. If is or omitted, the default equality comparer is used to compare keys. - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// - /// An that contains elements of type - /// where each grouping contains the outer element as the key and the matching inner elements. - /// - /// is . - /// is . - /// is . - /// is . - public static IEnumerable> GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer = null) - { - if (outer is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outer); - } - - if (inner is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.inner); - } - - if (outerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outerKeySelector); - } - - if (innerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.innerKeySelector); - } - - if (IsEmptyArray(outer)) - { - return []; - } - - return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, comparer); - } - public static IEnumerable GroupJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) => GroupJoin(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer: null); @@ -93,21 +45,6 @@ public static IEnumerable GroupJoin(this return GroupJoinIterator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); } - private static IEnumerable> GroupJoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer) - { - using IEnumerator e = outer.GetEnumerator(); - if (e.MoveNext()) - { - Lookup lookup = Lookup.CreateForJoin(inner, innerKeySelector, comparer); - do - { - TOuter item = e.Current; - yield return new GroupJoinGrouping(item, lookup[outerKeySelector(item)]); - } - while (e.MoveNext()); - } - } - private static IEnumerable GroupJoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer? comparer) { using IEnumerator e = outer.GetEnumerator(); @@ -123,22 +60,4 @@ private static IEnumerable GroupJoinIterator : IGrouping - { - private readonly TKey _key; - private readonly IEnumerable _elements; - - public GroupJoinGrouping(TKey key, IEnumerable elements) - { - _key = key; - _elements = elements; - } - - public TKey Key => _key; - - public IEnumerator GetEnumerator() => _elements.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } } diff --git a/src/libraries/System.Linq/src/System/Linq/Join.cs b/src/libraries/System.Linq/src/System/Linq/Join.cs index 265757b021cf96..677f6bd0eb8b36 100644 --- a/src/libraries/System.Linq/src/System/Linq/Join.cs +++ b/src/libraries/System.Linq/src/System/Linq/Join.cs @@ -272,83 +272,5 @@ private static IEnumerable JoinIterator( } } } - - /// - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner Inner) that are obtained by performing an inner join on two sequences. - /// or or or is . - /// - /// - /// This method is implemented by using deferred execution. The immediate return value is an object that stores - /// all the information that is required to perform the action. The query represented by this method is not - /// executed until the object is enumerated either by calling its GetEnumerator method directly or by - /// using foreach in C# or For Each in Visual Basic. - /// - /// - public static IEnumerable<(TOuter Outer, TInner Inner)> Join(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer = null) - { - if (outer is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outer); - } - - if (inner is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.inner); - } - - if (outerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outerKeySelector); - } - - if (innerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.innerKeySelector); - } - - if (IsEmptyArray(outer)) - { - return []; - } - - return JoinIterator(outer, inner, outerKeySelector, innerKeySelector, comparer); - } - - private static IEnumerable<(TOuter Outer, TInner Inner)> JoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer) - { - using IEnumerator e = outer.GetEnumerator(); - - if (e.MoveNext()) - { - Lookup lookup = Lookup.CreateForJoin(inner, innerKeySelector, comparer); - if (lookup.Count != 0) - { - do - { - TOuter item = e.Current; - Grouping? g = lookup.GetGrouping(outerKeySelector(item), create: false); - if (g is not null) - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } while (e.MoveNext()); - } - } - } } } diff --git a/src/libraries/System.Linq/src/System/Linq/LeftJoin.cs b/src/libraries/System.Linq/src/System/Linq/LeftJoin.cs index 59fa354aa928f8..097e2453d0167e 100644 --- a/src/libraries/System.Linq/src/System/Linq/LeftJoin.cs +++ b/src/libraries/System.Linq/src/System/Linq/LeftJoin.cs @@ -272,85 +272,5 @@ private static IEnumerable LeftJoinIterator - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter Outer, TInner? Inner) that are obtained by performing a left outer join on two sequences. - /// or or or is . - /// - /// - /// This method is implemented by using deferred execution. The immediate return value is an object that stores - /// all the information that is required to perform the action. The query represented by this method is not - /// executed until the object is enumerated either by calling its GetEnumerator method directly or by - /// using foreach in C# or For Each in Visual Basic. - /// - /// - public static IEnumerable<(TOuter Outer, TInner? Inner)> LeftJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer = null) - { - if (outer is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outer); - } - - if (inner is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.inner); - } - - if (outerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outerKeySelector); - } - - if (innerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.innerKeySelector); - } - - if (IsEmptyArray(outer)) - { - return []; - } - - return LeftJoinIterator(outer, inner, outerKeySelector, innerKeySelector, comparer); - } - - private static IEnumerable<(TOuter Outer, TInner? Inner)> LeftJoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer) - { - using IEnumerator e = outer.GetEnumerator(); - - if (e.MoveNext()) - { - Lookup innerLookup = Lookup.CreateForJoin(inner, innerKeySelector, comparer); - do - { - TOuter item = e.Current; - Grouping? g = innerLookup.GetGrouping(outerKeySelector(item), create: false); - if (g is null) - { - yield return (item, default); - } - else - { - int count = g._count; - TInner[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (item, elements[i]); - } - } - } - while (e.MoveNext()); - } - } } } diff --git a/src/libraries/System.Linq/src/System/Linq/RightJoin.cs b/src/libraries/System.Linq/src/System/Linq/RightJoin.cs index e54a0aea76ebe0..2485b7c13a281c 100644 --- a/src/libraries/System.Linq/src/System/Linq/RightJoin.cs +++ b/src/libraries/System.Linq/src/System/Linq/RightJoin.cs @@ -270,85 +270,5 @@ private static IEnumerable RightJoinIterator - /// Correlates the elements of two sequences based on matching keys. If is or omitted, the default equality comparer is used to compare keys. - /// - /// The first sequence to join. - /// The sequence to join to the first sequence. - /// A function to extract the join key from each element of the first sequence. - /// A function to extract the join key from each element of the second sequence. - /// An to hash and compare keys, or to use . - /// The type of the elements of the first sequence. - /// The type of the elements of the second sequence. - /// The type of the keys returned by the key selector functions. - /// An that has elements of type (TOuter? Outer, TInner Inner) that are obtained by performing a right outer join on two sequences. - /// or or or is . - /// - /// - /// This method is implemented by using deferred execution. The immediate return value is an object that stores - /// all the information that is required to perform the action. The query represented by this method is not - /// executed until the object is enumerated either by calling its GetEnumerator method directly or by - /// using foreach in C# or For Each in Visual Basic. - /// - /// - public static IEnumerable<(TOuter? Outer, TInner Inner)> RightJoin(this IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer = null) - { - if (outer is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outer); - } - - if (inner is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.inner); - } - - if (outerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.outerKeySelector); - } - - if (innerKeySelector is null) - { - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.innerKeySelector); - } - - if (IsEmptyArray(inner)) - { - return []; - } - - return RightJoinIterator(outer, inner, outerKeySelector, innerKeySelector, comparer); - } - - private static IEnumerable<(TOuter? Outer, TInner Inner)> RightJoinIterator(IEnumerable outer, IEnumerable inner, Func outerKeySelector, Func innerKeySelector, IEqualityComparer? comparer) - { - using IEnumerator e = inner.GetEnumerator(); - - if (e.MoveNext()) - { - Lookup outerLookup = Lookup.CreateForJoin(outer, outerKeySelector, comparer); - do - { - TInner item = e.Current; - Grouping? g = outerLookup.GetGrouping(innerKeySelector(item), create: false); - if (g is null) - { - yield return (default, item); - } - else - { - int count = g._count; - TOuter[] elements = g._elements; - for (int i = 0; i != count; ++i) - { - yield return (elements[i], item); - } - } - } - while (e.MoveNext()); - } - } } } diff --git a/src/libraries/System.Linq/tests/GroupJoinTests.cs b/src/libraries/System.Linq/tests/GroupJoinTests.cs index 9144b718423333..833ada49a5d89c 100644 --- a/src/libraries/System.Linq/tests/GroupJoinTests.cs +++ b/src/libraries/System.Linq/tests/GroupJoinTests.cs @@ -513,179 +513,5 @@ public void ForcedToEnumeratorDoesntEnumerate() var en = iterator as IEnumerator>; Assert.False(en is not null && en.MoveNext()); } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterEmptyInnerNonEmpty() - { - CustomerRec[] outer = []; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 98022, total = 50 }, - new OrderRec{ orderID = 97865, custID = 32103, total = 25 } - ]; - Assert.Empty(outer.GroupJoin(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterNonEmptyInnerEmpty() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 43434 }, - new CustomerRec{ name = "Bob", custID = 34093 } - ]; - OrderRec[] inner = []; - - var result = outer.GroupJoin(inner, e => e.custID, e => e.custID).ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal(outer[0], result[0].Key); - Assert.Empty(result[0]); - Assert.Equal(outer[1], result[1].Key); - Assert.Empty(result[1]); - } - - [Fact] - public void GroupJoinWithoutResultSelector_SingleElementEachAndMatches() - { - CustomerRec[] outer = [new CustomerRec{ name = "Tim", custID = 43434 }]; - OrderRec[] inner = [new OrderRec{ orderID = 97865, custID = 43434, total = 25 }]; - - var result = outer.GroupJoin(inner, e => e.custID, e => e.custID).ToList(); - - Assert.Single(result); - Assert.Equal(outer[0], result[0].Key); - Assert.Single(result[0]); - Assert.Equal(inner[0], result[0].First()); - } - - [Fact] - public void GroupJoinWithoutResultSelector_InnerSameKeyMoreThanOneElementAndMatches() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 }, - new CustomerRec{ name = "Bob", custID = 9865 } - ]; - OrderRec[] inner = - [ - new OrderRec{ orderID = 97865, custID = 1234, total = 25 }, - new OrderRec{ orderID = 34390, custID = 1234, total = 19 }, - new OrderRec{ orderID = 34390, custID = 9865, total = 19 } - ]; - - var result = outer.GroupJoin(inner, e => e.custID, e => e.custID).ToList(); - - Assert.Equal(2, result.Count); - Assert.Equal(outer[0], result[0].Key); - Assert.Equal(2, result[0].Count()); - Assert.Equal(outer[1], result[1].Key); - Assert.Single(result[1]); - } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterNull() - { - CustomerRec[] outer = null; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 98022, total = 50 } - ]; - - AssertExtensions.Throws("outer", () => outer.GroupJoin(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_InnerNull() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 } - ]; - OrderRec[] inner = null; - - AssertExtensions.Throws("inner", () => outer.GroupJoin(inner, e => e.custID, e => e.custID)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_OuterKeySelectorNull() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 } - ]; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 98022, total = 50 } - ]; - - AssertExtensions.Throws("outerKeySelector", () => outer.GroupJoin(inner, null, e => e.custID)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_InnerKeySelectorNull() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 } - ]; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 98022, total = 50 } - ]; - - AssertExtensions.Throws("innerKeySelector", () => outer.GroupJoin(inner, e => e.custID, null)); - } - - [Fact] - public void GroupJoinWithoutResultSelector_CanIterateMultipleTimes() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 } - ]; - OrderRec[] inner = - [ - new OrderRec{ orderID = 97865, custID = 1234, total = 25 } - ]; - - var result = outer.GroupJoin(inner, e => e.custID, e => e.custID).ToList(); - - Assert.Single(result); - - // Iterate the grouped elements multiple times - Assert.Single(result[0]); - Assert.Single(result[0]); - Assert.Equal(inner[0], result[0].First()); - Assert.Equal(inner[0], result[0].First()); - } - - [Fact] - public void GroupJoinWithoutResultSelector_CustomComparer() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 1234 }, - new CustomerRec{ name = "Bob", custID = 9865 }, - new CustomerRec{ name = "Robert", custID = 9895 } - ]; - AnagramRec[] inner = - [ - new AnagramRec{ name = "Robert", orderID = 93483, total = 19 }, - new AnagramRec{ name = "miT", orderID = 93489, total = 45 } - ]; - - var result = outer.GroupJoin(inner, e => e.name, e => e.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(3, result.Count); - Assert.Equal(outer[0], result[0].Key); - Assert.Single(result[0]); - Assert.Equal(inner[1], result[0].First()); - Assert.Equal(outer[1], result[1].Key); - Assert.Empty(result[1]); - Assert.Equal(outer[2], result[2].Key); - Assert.Single(result[2]); - Assert.Equal(inner[0], result[2].First()); - } } } diff --git a/src/libraries/System.Linq/tests/JoinTests.cs b/src/libraries/System.Linq/tests/JoinTests.cs index 5fc9571f0854b5..4504fc47521d5c 100644 --- a/src/libraries/System.Linq/tests/JoinTests.cs +++ b/src/libraries/System.Linq/tests/JoinTests.cs @@ -417,109 +417,5 @@ public void ForcedToEnumeratorDoesntEnumerate() var en = iterator as IEnumerator; Assert.False(en is not null && en.MoveNext()); } - - [Fact] - public void TupleJoin_Basic() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 }, - new CustomerRec{ name = "Robert", custID = 99022 } - ]; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 99022, total = 50 }, - new OrderRec{ orderID = 43421, custID = 29022, total = 20 }, - new OrderRec{ orderID = 95421, custID = 98022, total = 9 } - ]; - - var result = outer.Join(inner, o => o.custID, i => i.custID); - - var expected = outer.Join(inner, o => o.custID, i => i.custID, (o, i) => (Outer: o, Inner: i)); - - Assert.Equal(expected, result); - } - - [Fact] - public void TupleJoin_EmptyOuter() - { - CustomerRec[] outer = []; - OrderRec[] inner = - [ - new OrderRec{ orderID = 45321, custID = 98022, total = 50 } - ]; - - Assert.Empty(outer.Join(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleJoin_EmptyInner() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Prakash", custID = 98022 } - ]; - OrderRec[] inner = []; - - Assert.Empty(outer.Join(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleJoin_WithComparer() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 } - ]; - AnagramRec[] inner = - [ - new AnagramRec{ name = "miT", orderID = 43455, total = 10 }, - new AnagramRec{ name = "Prakash", orderID = 323232, total = 9 } - ]; - - var result = outer.Join(inner, o => o.name, i => i.name, new AnagramEqualityComparer()); - - Assert.Equal(2, result.Count()); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.name == "Prakash"); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - } - - [Fact] - public void TupleJoin_OuterNull() - { - CustomerRec[] outer = null; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outer", () => outer.Join(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleJoin_InnerNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = null; - - AssertExtensions.Throws("inner", () => outer.Join(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outerKeySelector", () => outer.Join(inner, (Func)null, i => i.custID)); - } - - [Fact] - public void TupleJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("innerKeySelector", () => outer.Join(inner, o => o.custID, (Func)null)); - } } } diff --git a/src/libraries/System.Linq/tests/LeftJoinTests.cs b/src/libraries/System.Linq/tests/LeftJoinTests.cs index c5daddd5ec4182..43e81014aad5b1 100644 --- a/src/libraries/System.Linq/tests/LeftJoinTests.cs +++ b/src/libraries/System.Linq/tests/LeftJoinTests.cs @@ -446,99 +446,5 @@ public void ForcedToEnumeratorDoesntEnumerate() var en = iterator as IEnumerator; Assert.False(en is not null && en.MoveNext()); } - - [Fact] - public void TupleLeftJoin_Basic() - { - string[] outer = ["Prakash", "Tim", "Robert"]; - string[] inner = ["prakash", "robert"]; - - var result = outer.LeftJoin(inner, o => o.ToLowerInvariant(), i => i.ToLowerInvariant()).ToList(); - - var expected = outer.LeftJoin( - inner, - o => o.ToLowerInvariant(), - i => i.ToLowerInvariant(), - (o, i) => (Outer: o, Inner: i)).ToList(); - - Assert.Equal(expected, result); - } - - [Fact] - public void TupleLeftJoin_EmptyOuter() - { - string[] outer = []; - string[] inner = ["prakash"]; - - Assert.Empty(outer.LeftJoin(inner, o => o, i => i)); - } - - [Fact] - public void TupleLeftJoin_EmptyInner() - { - string[] outer = ["Prakash"]; - string[] inner = Array.Empty(); - - var result = outer.LeftJoin(inner, o => o, i => i).ToList(); - Assert.Single(result); - Assert.Equal("Prakash", result[0].Outer); - Assert.Null(result[0].Inner); - } - - [Fact] - public void TupleLeftJoin_WithComparer() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Prakash", custID = 98022 }, - new CustomerRec{ name = "Tim", custID = 99021 } - ]; - AnagramRec[] inner = - [ - new AnagramRec{ name = "miT", orderID = 43455, total = 10 } - ]; - - var result = outer.LeftJoin(inner, o => o.name, i => i.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Prakash" && r.Inner.name == null); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - } - - [Fact] - public void TupleLeftJoin_OuterNull() - { - CustomerRec[] outer = null; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outer", () => outer.LeftJoin(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleLeftJoin_InnerNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = null; - - AssertExtensions.Throws("inner", () => outer.LeftJoin(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleLeftJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outerKeySelector", () => outer.LeftJoin(inner, (Func)null, i => i.custID)); - } - - [Fact] - public void TupleLeftJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("innerKeySelector", () => outer.LeftJoin(inner, o => o.custID, (Func)null)); - } } } diff --git a/src/libraries/System.Linq/tests/RightJoinTests.cs b/src/libraries/System.Linq/tests/RightJoinTests.cs index 433b1fc21165af..9eb51920f48be3 100644 --- a/src/libraries/System.Linq/tests/RightJoinTests.cs +++ b/src/libraries/System.Linq/tests/RightJoinTests.cs @@ -443,100 +443,5 @@ public void ForcedToEnumeratorDoesntEnumerate() var en = iterator as IEnumerator; Assert.False(en is not null && en.MoveNext()); } - - [Fact] - public void TupleRightJoin_Basic() - { - string[] outer = ["prakash", "tim"]; - string[] inner = ["prakash", "robert", "unknown"]; - - var result = outer.RightJoin(inner, o => o, i => i).ToList(); - - (string? Outer, string Inner)[] expected = - [ - ("prakash", "prakash"), - (null, "robert"), - (null, "unknown") - ]; - - Assert.Equal(expected, result); - } - - [Fact] - public void TupleRightJoin_EmptyOuter() - { - string[] outer = []; - string[] inner = ["prakash"]; - - var result = outer.RightJoin(inner, o => o, i => i).ToList(); - Assert.Single(result); - Assert.Null(result[0].Outer); - Assert.Equal("prakash", result[0].Inner); - } - - [Fact] - public void TupleRightJoin_EmptyInner() - { - string[] outer = ["Prakash"]; - string[] inner = Array.Empty(); - - Assert.Empty(outer.RightJoin(inner, o => o, i => i)); - } - - [Fact] - public void TupleRightJoin_WithComparer() - { - CustomerRec[] outer = - [ - new CustomerRec{ name = "Tim", custID = 99021 } - ]; - AnagramRec[] inner = - [ - new AnagramRec{ name = "miT", orderID = 43455, total = 10 }, - new AnagramRec{ name = "Prakash", orderID = 323232, total = 9 } - ]; - - var result = outer.RightJoin(inner, o => o.name, i => i.name, new AnagramEqualityComparer()).ToList(); - - Assert.Equal(2, result.Count); - Assert.Contains(result, r => r.Outer.name == "Tim" && r.Inner.name == "miT"); - Assert.Contains(result, r => r.Outer.name == null && r.Inner.name == "Prakash"); - } - - [Fact] - public void TupleRightJoin_OuterNull() - { - CustomerRec[] outer = null; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outer", () => outer.RightJoin(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleRightJoin_InnerNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = null; - - AssertExtensions.Throws("inner", () => outer.RightJoin(inner, o => o.custID, i => i.custID)); - } - - [Fact] - public void TupleRightJoin_OuterKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("outerKeySelector", () => outer.RightJoin(inner, (Func)null, i => i.custID)); - } - - [Fact] - public void TupleRightJoin_InnerKeySelectorNull() - { - CustomerRec[] outer = [new CustomerRec{ name = "Prakash", custID = 98022 }]; - OrderRec[] inner = [new OrderRec{ orderID = 45321, custID = 98022, total = 50 }]; - - AssertExtensions.Throws("innerKeySelector", () => outer.RightJoin(inner, o => o.custID, (Func)null)); - } } }