C# 8: Slicing with Indexes and Ranges

C# 8.0 brings us another nice feature called slicing. In order to make it possible, two new concepts are introduced: Indexes and Ranges.

Let’s see how this tiny feature is supposed to make our life easier 🙂

Goal of slicing

The main purpose of introducing slicing into the language is to make working with arrays and strings easier.

Currently, when you want to retrieve a fragment of an array (X elements from the array, located for instance in its middle), you can use LINQ, i.e. combination of Take and Skip methods. You can also create some extension method to provide kind of slicing.

To illustrate the current way, using LINQ to retrieve only 2nd, 3rd and 4th elements of an array looks as follows:

var array = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G' , 'H'};
var arraySlice = array.Skip(1).Take(3).ToArray(); // contains 'B', 'C' and 'D'

C# community and designers decided it’s not convenient enough, so are now adding to C# 8 indexes and ranges (in order to provide slicing) 🙂

Index

C# 8.0 comes along with a new object – System.Index. It’s a structure internally and looks as follows:

C# 8 indexes and ranges: System.Index structure - .NET Core 3.0.0-preview-27324-5
System.Index structure – .NET Core 3.0.0-preview-27324-5

What’s interesting here, is that the constructor takes the value of the index and boolean flag fromEnd. Let’s see how we can use it in practice:

var array = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
Index idx1 = 2; // 2nd element from the beginning
Index idx2 = ^3; // 3rd element from the end (^)
Console.WriteLine($"{array[idx1]}, {array[idx2]}"); // prints "C, F"

While the first printed value is nothing special, as you can see we can now use the hat operator (^) in order to index from the end. The following also works:

var array = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
Console.WriteLine($"{array[^3]}"); // prints "F" (3rd element from the end)

It means that the ^ operator is a syntactic sugar for Index. I allowed myself to check the IL produced:

C# 8 indexes and ranges: IL Code behind ^ (hat operator)
IL Code behind ^ (hat operator)

As we suspected – an instance of Index is created, passing 3 as value and true as fromEnd (see the constructor parameters above).

Range

Another concept which uses Indexes is a new structural data type – System.Range:

C# 8 indexes and ranges: System.Range structure - .NET Core 3.0.0-preview-27324-5
System.Range structure – .NET Core 3.0.0-preview-27324-5

As you can see, it really uses Indexes. We can even try creating it on our own:

var array = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
Range r = Range.Create(2, ^1); // range from 2nd to
// 1st element from the end
Console.WriteLine(array[r]); // prints "CDEFG"
view raw RangeCSharp8.cs hosted with ❤ by GitHub

This doesn’t really make extracting data from the arrays better than Skip-Take LINQ, does it?

Fortunately, there’s another friendly C# language element introduced called range expression. It can be written as x..y and used directly for indexing:

var array = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H' };
Console.WriteLine(array[2..^1]); // prints "CDEFG"

This looks much better! Let’s see how C# compiler translated our 2 lines of code by looking at the pseudo-C# IL produced:

C# 8 indexes and ranges: IL (C# pseudo-code) produced when using range expression
IL (C# pseudo-code) produced when using range expression

Even though we could achieve the same with much less LINQ, C# compiler does a lot of stuff for us, keeping our code simpler to grasp.

Ranges in strings

All these operations apply also to strings:

var story = "C# 8 is going to be great!";
Console.WriteLine(story[^6..^0]); // prints "great!" (last 6 chars)

Ranges in foreach loop

Next interesting usage is in the foreach loop:

var devs = new Developer[]
{
new Developer("Dawid"),
new Developer("Mark"),
new Developer("John"),
new Developer("Alice"),
new Developer("Kate")
};
foreach (var dev in devs[1..^2]) // prints "MarkJohn"
{
Console.Write(dev.FirstName);
}

Summary

I see these “little” C# 8 indexes and ranges as another helpful feature. It’s less breaking and controversial than nullable reference types, still making us write less C# code in the future.

If you’d like to dig the feature even more, I encourage you to read the discussions about it on GitHub, which I always find very interesting 😉

Developers, what do you think about C# 8 indexes and ranges? 🤔

.NET full stack web developer & digital nomad
0 0 votes
Article Rating
Subscribe
Notify of
guest
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
trackback
String Manipulation.Find String Between 2 Indexes - Programming Questions And Solutions Blog
1 year ago