How to print out a reversed array using range?

Solution 1:

Reverse ranges are not so much a limitation on the Range type, but rather a limitation on the Span (and related) types – which assume a positive increment. The rational is that many of the low-level optimizations and usage scenarios for a slice of an array are only geared toward the basic notion of a "pointer plus size". (Link to Range usages in Framework)

While this won't allow a reverse Span to be passed around, an extension method could be used to provide an easy and performant syntax for reverse range enumeration:

public static class RangeExtensions
{
    public static int Normalize(this Index index, int length) => 
           index.IsFromEnd ? length - index.Value : index.Value;

    public static (int start, int end) Normalize(this Range range, int length) => 
           (range.Start.Normalize(length), range.End.Normalize(length));

    public static IEnumerable<T> Enumerate<T>(this T[] items, Range range)
    {
        var (start, end) = range.Normalize(items.Length);

        return start <= end ? items[range] : GetRangeReverse();

        IEnumerable<T> GetRangeReverse()
        {
            for (int i = start; i >= end; i--)
                yield return items[i];
        }
    }
}

...

var numbers = Enumerable.Range(0, 10).ToArray();

foreach (var num in numbers.Enumerate(^3..1))
    Console.WriteLine(num);

Solution 2:

I couldn't find anything that says that's possible. But, it doesn't appear to be a language restriction, as we can create a range like Range r = 5..1; and that doesn't throw exceptions, so it must be the implementation of Array[Range] and other types, like string that doesn't accept it. That put, you can probably create an method that accepts a Range and does what you want.

Edit: I made the following method that works with arrays:

static T[] MySlice<T>(T[] array, Range r)
{
    //Transforms indexes "from end" to indexes "from start"    
    if(r.Start.IsFromEnd){
        var startIdx = array.Length - r.Start.Value;
        r = new Range(startIdx,r.End);
    }
    if(r.End.IsFromEnd){
        var endIdx = array.Length - r.End.Value;
        r = new Range(r.Start,endIdx);
    }
    //Check if start value is greater than end value. If so, invert it
    if(r.Start.Value > r.End.Value)
    {                
        r = new Range(r.End,r.Start);
        var invArr = array[r];
        Array.Reverse(invArr);
        return invArr;
    }
    return array[r];
}

And you can use like

int[] arr = Enumerable.Range(0,10).ToArray();
Range r = ^0..0;

foreach(var v in MySlice(arr,r)){
    Console.WriteLine(v);
}

Which outputs:

9
8
7
6
5
4
3
2
1
0