What's Coming in C# 8.0? Ranges and Indices

Ever wanted simple syntax for slicing out a part of an array, string or span? Now you can!

Let's consider the following program:

using System.Collections.Generic;
using static System.Console;

class Program
{
    static void Main(string[] args)
    {
        foreach (var name in GetNames())
        {
            WriteLine(name);
        }
    }

    static IEnumerable<string> GetNames()
    {
        string[] names =
        {
            "Christopher", "Natasha", "Jean", "Matthew", "Luke"
        };
        foreach (var name in names)
        {
            yield return name;
        }
    }
}

As you might expect, this program just prints the 5 names in the console.

Ranges and Indices

With new Ranges syntax, we can modify the foreach to iterate over names 1 to 4. For example:

foreach (var name in names[1..4])

The endpoint is exclusive (element 4 is not included). 1..4 is actually a range expression, and it doesn't have to occur like here, as part of an indexing operation. It has a type of its own, called Range. If we wanted, we could pull it out into its own variable, and it would work the same:

Range range = 1..4; 
foreach (var name in names[range])

The endpoints of a range expression don't have to be ints. In fact they're of a type, Index, that non-negative ints convert to. But you can also create an Index with a new ^ operator, meaning "from end". So ^1 is one from the end:

foreach (var name in names[1..^1])

This lobs off an element at each end of the array, producing an array with the middle three elements, so the result would be:

Natasha
Jean
Matthew

Range expressions can be open at either or both ends. ..^1 means the same as 0..^1. 1.. means the same as 1..^0. And .. means the same as 0..^0: beginning to end. Try them all out and see! Try mixing and matching "from beginning" and "from end" Indexes at either end of a Range and see what happens.