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.
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 betweenvoid MemoryExtensions.Reverse<T>(this Span<T>)andIEnumerable<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 forarray.Reverse(), is worth the tradeoff.Elaborating on the break: today,
array.Reverse()binds toEnumerable.Reverse<T>(IEnumerable<T>), andMemoryExtensions.Reverse(Span<T>)isn't applicable. In C# 14, this changes; both of these methods are applicable in extension form, and theSpan<T>version is preferred overIEnumerable<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 ofReversefor some reason, is a behavior break). By introducingEnumerable.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
Enumerableextensions 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-basedEnumerablemethods.API Proposal
API Usage
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.