C# Ranges and Indexes
Tags: csharp, dotnet
Published: 2021-06-22 13:38:01

---
title: C# Ranges and Indexes
published: true
description: In this tutorial, we're going to go through two new .NET types - `System.Index`, `System.Range` and cover appropriate operators: `^` and `..`. If you are interested in learning more about C# language, this is for you.
tags: csharp, dotnet
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v1d7a31l0exzhi4yp8gc.png
---

#### Intro
In this tutorial, we're going to go through two new .NET types - `System.Index`, `System.Range` and cover appropriate operators: `^` and `..`.

If you are interested in learning more about C# language, this is for you.

You’ll be able to use the skills and lessons in this tutorial in the real dev world when you work on any project using C#.

It will provide you with a more elegant way to work with sequences and laconic syntax to access elements. Long story short - to use modern language constructions to write easily readable and understandable code.

Ranges and Indexes were introduced as part of .NET Standard 2.1. This is C# 8 feature. It is available in .NET 5, netcore 3.0. It is not supported by .NET Framework. It can be applied for  [arrays](https://docs.microsoft.com/en-us/dotnet/api/system.array?view=net-5.0), [spans](https://docs.microsoft.com/en-us/dotnet/api/system.span-1?view=net-5.0), and [readonly spans](https://docs.microsoft.com/ru-ru/dotnet/api/system.readonlyspan-1?view=net-5.0).

#### Preparations

First, go to your favorite IDE, it might be Visual Studio, VS Code, Rider, LINQPad, etc. Make sure to start with nothing open or running (except your computer!) I prefer Visual Studio

Next, create a new project and go through the steps.

#### Steps

The dataset I’m going to use for this tutorial is just a string array of languages.

Create a collection. Let's create an array with the languages.

```c#
var languages = new string[] { "Spanish", "English", "Japanese", "French", "German", "Russian", "Italian", "Korean", "Chinese" };
```

##### Index

How can we get the second element - "English"? It is pretty easy to do, we just have to pass the index (remember that the numeration if indexes in collections in C# starts from 0)

```c#
int index = 1;
var english = languages[index];
Console.WriteLine(english); // Output: English
```

Instead of `int` variable we can use `Index` type for doing the same:

```c#
Index index1 = 1;
var english2 = languages[index1];
Console.WriteLine(english2);
```

Here is another way to create index.  `Index` is value type so when we do `new Index()` it will set the default value to `0`

```c#
var index2 = new Index(); // zero by default because this is a structure
var spanish = languages[index2];
Console.WriteLine(spanish);
```

We can pass the index value as a parameter to the constructor

```c#
var index3 = new Index(2);
var japanese = languages[index3];
Console.WriteLine(japanese);
```



Probably for now you might ask what is the benefit to use index rather than just integer variable? Okay, probably for accessing the first or second elements there are no many benefits. But in the next examples, we will see getting the last element and will see much more benefits when we will try indexes with ranges together.

The second question here is how can we get the last element? Okay, we can simply get the length of the array and subtract `1`. (because of the first element has the index `0` that's way the last element has the index `last element - 1`)

```c#
var lastIndex1 = languages.Length - 1;
var chinese1 = languages[lastIndex1];
Console.WriteLine(chinese1);
```

And the same by using Index:

```c#
Index lastIndex2 = ^1;
var chinese2 = languages[lastIndex2];
Console.WriteLine(chinese2);
```

We can do both above examples in one line. 

```c#
Console.WriteLine(languages[languages.Length - 2]); // Korean
```

vs

```c#
Console.WriteLine(languages[^2]); // Korean
```

The struct `Index` has overwritten method `Equals` so we can check the equality of the two indexes. 

```c#
var equals = index1.Equals(index2);
Console.WriteLine(equals); // false
```

##### Range

Usually, users are forced to implement complex structures to filter/operate on slices of memory or resort to LINQ methods like `list.Skip(5).Take(2)`. With the addition of `System.Span<T>` and other similar types, it becomes more important to have this kind of operation supported on a deeper level in the language/runtime and have the interface unified.

Range operator `..` is a binary infix operator that accepts two expressions, or both expressions can be omitted.

```c#
Range myRange1 = 1..4;
```

This can be used with indexes together:

```c#
Index start = 1;
Index end = 4;
Range myRange2 = start..end;
```

The following will output the `1`, `2` and `3` elements from array:

```c#
string[] languagesRange = languages[1..4];
foreach (var language in languagesRange)
{
    Console.WriteLine(language);
}
```

A bit more interesting usages.

3 last elements:  

```c#
string[] languagesRange1 = languages[^3..];
```

From start to pre-last element (every except the last one)

```c#
string[] languagesRange2 = languages[..^1];
```

3 elements before pre-last element

```c#
string[] languagesRange3 = languages[^4..^1];
```



As I mentioned earlier the same we can do with `Span` 

```c#
Span<string> languagesSpan = languages;
Span<string> selectedLanguagesSpan = languagesSpan[1..4];
foreach (var language in selectedLanguagesSpan)
{
    Console.WriteLine(language);
}
```

#### Thank you
Thank you very much for reading. I hope it brought something new to you. Hope you'll find a chance to give it a try for these features in your projects. Also, I would appreciate any feedback from you. Feel free to post your comments below.

The source code can be found [here](https://github.com/andreisfedotov/codenewbie/tree/main/Range_and_Index).