Skip to content

Commit

Permalink
Implement Enumerable.Reverse(TSource[]) (#107957)
Browse files Browse the repository at this point in the history
Closes #107723.
  • Loading branch information
333fred authored Sep 25, 2024
1 parent cf165a7 commit d6ac24c
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/libraries/System.Linq.Queryable/tests/Queryable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ public static void MatchSequencePattern()
nameof(Enumerable.Prepend),
nameof(Enumerable.ToHashSet),
nameof(Enumerable.TryGetNonEnumeratedCount),
nameof(Enumerable.Reverse),
"Fold",
"LeftJoin",
}
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Linq/ref/System.Linq.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ public static System.Collections.Generic.IEnumerable<
public static System.Collections.Generic.IEnumerable<int> Range(int start, int count) { throw null; }
public static System.Collections.Generic.IEnumerable<TResult> Repeat<TResult>(TResult element, int count) { throw null; }
public static System.Collections.Generic.IEnumerable<TSource> Reverse<TSource>(this System.Collections.Generic.IEnumerable<TSource> source) { throw null; }
public static System.Collections.Generic.IEnumerable<TSource> Reverse<TSource>(this TSource[] source) { throw null; }
public static System.Collections.Generic.IEnumerable<TResult> SelectMany<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, System.Collections.Generic.IEnumerable<TResult>> selector) { throw null; }
public static System.Collections.Generic.IEnumerable<TResult> SelectMany<TSource, TResult>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, int, System.Collections.Generic.IEnumerable<TResult>> selector) { throw null; }
public static System.Collections.Generic.IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this System.Collections.Generic.IEnumerable<TSource> source, System.Func<TSource, System.Collections.Generic.IEnumerable<TCollection>> collectionSelector, System.Func<TSource, TCollection, TResult> resultSelector) { throw null; }
Expand Down
15 changes: 15 additions & 0 deletions src/libraries/System.Linq/src/System/Linq/Reverse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,21 @@ public static IEnumerable<TSource> Reverse<TSource>(this IEnumerable<TSource> so
return new ReverseIterator<TSource>(source);
}

public static IEnumerable<TSource> Reverse<TSource>(this TSource[] source)
{
if (source is null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}

if (source.Length == 0)
{
return [];
}

return new ReverseIterator<TSource>(source);
}

/// <summary>
/// An iterator that yields the items of an <see cref="IEnumerable{TSource}"/> in reverse.
/// </summary>
Expand Down
1 change: 1 addition & 0 deletions src/libraries/System.Linq/tests/ConsistencyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ private static IEnumerable<string> GetExcludedMethods()
nameof(Enumerable.ToList),
nameof(Enumerable.ToHashSet),
nameof(Enumerable.TryGetNonEnumeratedCount),
nameof(Enumerable.Reverse),
"Fold",
"LeftJoin",
};
Expand Down
37 changes: 36 additions & 1 deletion src/libraries/System.Linq/tests/ReverseTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public class ReverseTests : EnumerableTests
[Fact]
public void InvalidArguments()
{
AssertExtensions.Throws<ArgumentNullException>("source", () => Enumerable.Reverse<string>(null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Enumerable.Reverse<string>((IEnumerable<string>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Enumerable.Reverse<string>((string[])null));
}

[Theory]
Expand Down Expand Up @@ -48,6 +49,40 @@ public void Reverse<T>(IEnumerable<T> source)
Assert.Equal(actual, actual); // Repeat the enumeration against itself.
}

[Theory]
[MemberData(nameof(ReverseData))]
public void ReverseArray<T>(IEnumerable<T> source)
{
T[] expected = source.ToArray();
Array.Reverse(expected);

IEnumerable<T> actual = source.ToArray().Reverse();

Assert.Equal(expected, actual);
Assert.Equal(expected.Count(), actual.Count()); // Count may be optimized.
Assert.Equal(expected, actual.ToArray());
Assert.Equal(expected, actual.ToList());

Assert.Equal(expected.FirstOrDefault(), actual.FirstOrDefault());
Assert.Equal(expected.LastOrDefault(), actual.LastOrDefault());

for (int i = 0; i < expected.Length; i++)
{
Assert.Equal(expected[i], actual.ElementAt(i));

Assert.Equal(expected.Skip(i), actual.Skip(i));
Assert.Equal(expected.Take(i), actual.Take(i));
}

Assert.Equal(default(T), actual.ElementAtOrDefault(-1));
Assert.Equal(default(T), actual.ElementAtOrDefault(expected.Length));

Assert.Equal(expected, actual.Select(_ => _));
Assert.Equal(expected, actual.Where(_ => true));

Assert.Equal(actual, actual); // Repeat the enumeration against itself.
}

[Theory, MemberData(nameof(ReverseData))]
public void RunOnce<T>(IEnumerable<T> source)
{
Expand Down

0 comments on commit d6ac24c

Please sign in to comment.