Skip to content

[API Proposal]: Enumerable.Reverse<T>(T[]) #107723

@333fred

Description

@333fred

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.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions