-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
The BCL has long resisted adding new array-based enumerable implementations, and with good reason; however, C# 14 is going to introduce a new feature, first-class spans, which unfortunately changes what array.Reverse() means between void MemoryExtensions.Reverse<T>(this Span<T>) and IEnumerable<T> Enumerable.Reverse<T>(this IEnumerable<T>). Overall, the benefits of this new feature will pretty significantly benefit the BCL by reducing the number of overloads of various things that are necessary; in talking with @stephentoub, we believe that adding an array-based overload, only for this specific case, and only to ensure source-compatibility for array.Reverse(), is worth the tradeoff.
Elaborating on the break: today, array.Reverse() binds to Enumerable.Reverse<T>(IEnumerable<T>), and MemoryExtensions.Reverse(Span<T>) isn't applicable. In C# 14, this changes; both of these methods are applicable in extension form, and the Span<T> version is preferred over IEnumerable<T>. This means the behavior changes from "return a new stream, reversed from the input stream", to "in-place reverse the array, and return nothing". This is almost certainly a source-breaking change (or, for the person that ignored the result of Reverse for some reason, is a behavior break). By introducing Enumerable.Reverse<T>(T[]), that method will be the most-specific overload among the 3 applicable methods, and existing behavior will be preserved.
Important note: this does not mean that we are reopening the door for array-based Enumerable extensions overall. We are specifically looking at this method to fix a source-breaking change in C# 14. This proposal should not be used to justify further expansion of array-based Enumerable methods.
API Proposal
namespace System.Linq;
public static class Enumerable
{
public static IEnumerable<TSource> Reverse<TSource>(this T[] source);
}API Usage
using System;
using System.Linq;
int[] l = [1, 2, 3];
foreach (var v in l.Reverse())
Console.WriteLine(v);Alternative Designs
No response
Risks
This is a fairly low-risk API, so long as we don't go using it to justify further array-based Enumerable overloads.