diff --git a/src/libraries/System.Linq.Queryable/tests/Queryable.cs b/src/libraries/System.Linq.Queryable/tests/Queryable.cs index 1ffd4b4fc17fb..f6b125c984f59 100644 --- a/src/libraries/System.Linq.Queryable/tests/Queryable.cs +++ b/src/libraries/System.Linq.Queryable/tests/Queryable.cs @@ -96,6 +96,7 @@ public static void MatchSequencePattern() nameof(Enumerable.Prepend), nameof(Enumerable.ToHashSet), nameof(Enumerable.TryGetNonEnumeratedCount), + nameof(Enumerable.Reverse), "Fold", "LeftJoin", } diff --git a/src/libraries/System.Linq/ref/System.Linq.cs b/src/libraries/System.Linq/ref/System.Linq.cs index 7e89e2bf1ac1c..85ab6fd35d0fd 100644 --- a/src/libraries/System.Linq/ref/System.Linq.cs +++ b/src/libraries/System.Linq/ref/System.Linq.cs @@ -159,6 +159,7 @@ public static System.Collections.Generic.IEnumerable< public static System.Collections.Generic.IEnumerable Range(int start, int count) { throw null; } public static System.Collections.Generic.IEnumerable Repeat(TResult element, int count) { throw null; } public static System.Collections.Generic.IEnumerable Reverse(this System.Collections.Generic.IEnumerable source) { throw null; } + public static System.Collections.Generic.IEnumerable Reverse(this TSource[] source) { 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/Reverse.cs b/src/libraries/System.Linq/src/System/Linq/Reverse.cs index 0eba290b7c7f4..657a18a1bf8f9 100644 --- a/src/libraries/System.Linq/src/System/Linq/Reverse.cs +++ b/src/libraries/System.Linq/src/System/Linq/Reverse.cs @@ -23,6 +23,21 @@ public static IEnumerable Reverse(this IEnumerable so return new ReverseIterator(source); } + public static IEnumerable Reverse(this TSource[] source) + { + if (source is null) + { + ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source); + } + + if (source.Length == 0) + { + return []; + } + + return new ReverseIterator(source); + } + /// /// An iterator that yields the items of an in reverse. /// diff --git a/src/libraries/System.Linq/tests/ConsistencyTests.cs b/src/libraries/System.Linq/tests/ConsistencyTests.cs index 746efa6143943..99f94d1cae3c3 100644 --- a/src/libraries/System.Linq/tests/ConsistencyTests.cs +++ b/src/libraries/System.Linq/tests/ConsistencyTests.cs @@ -44,6 +44,7 @@ private static IEnumerable GetExcludedMethods() nameof(Enumerable.ToList), nameof(Enumerable.ToHashSet), nameof(Enumerable.TryGetNonEnumeratedCount), + nameof(Enumerable.Reverse), "Fold", "LeftJoin", }; diff --git a/src/libraries/System.Linq/tests/ReverseTests.cs b/src/libraries/System.Linq/tests/ReverseTests.cs index 1cd337a975036..d780b27b06390 100644 --- a/src/libraries/System.Linq/tests/ReverseTests.cs +++ b/src/libraries/System.Linq/tests/ReverseTests.cs @@ -11,7 +11,8 @@ public class ReverseTests : EnumerableTests [Fact] public void InvalidArguments() { - AssertExtensions.Throws("source", () => Enumerable.Reverse(null)); + AssertExtensions.Throws("source", () => Enumerable.Reverse((IEnumerable)null)); + AssertExtensions.Throws("source", () => Enumerable.Reverse((string[])null)); } [Theory] @@ -48,6 +49,40 @@ public void Reverse(IEnumerable source) Assert.Equal(actual, actual); // Repeat the enumeration against itself. } + [Theory] + [MemberData(nameof(ReverseData))] + public void ReverseArray(IEnumerable source) + { + T[] expected = source.ToArray(); + Array.Reverse(expected); + + IEnumerable 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(IEnumerable source) {