Indices and Ranges in C#

Indices and Ranges in C# 8 with Examples

In this article, I am going to discuss Indices and Ranges in C# 8 with Examples. Please read our previous article where we discussed Asynchronous Disposable in C# 8 with Examples. As we already know about the Range and Indices. We use them several times in our programs, they provide a short syntax to represent or access a single or a range of elements from the given sequence or collections. In this article, we will learn what’s newly added in the range and indices in C# 8.0. The Range and Indexes make the C# syntax simpler and more readable.

Indices and Ranges in C#

Ranges and Indices in C# allow more natural syntax for accessing single items or ranges in a sequence. This language support relies on two new types and two new operators. They are as follows:

Two New Types:
  1. System.Range: It represents a sub-range of the given sequence or collection.
  2. System.Index: It represents an index into the given sequence or collection.
Two New Operators:

^ Operator: It is known as the index from the end operator. It returns an index that is relative to the end of the sequence or collection. It is the most compact and easiest way to find the end elements compare to earlier methods.
// Old Method
var lastvalue = myArray[myArray.Length-1]
// New Method
var lastvalue = myArray[^1]

.. Operator: It is known as the range operator. And it specifies the start and end as its operands of the given range. It is the most compact and easiest way to find the range of the elements from the specified sequence or collection in comparison to earlier methods.
// Old Method
var arr = myArray.GetRange(1, 5);
// New Method
var arr = myArray[2..3]

These new operators make our code cleaner and more readable. If this is not clear at the moment then don’t worry, we will try to make you understand with examples.

Index in C# 8

The Index is the new feature introduced in C# 8 and it is implemented in System.Index, and it is an excellent way to index a collection from the ending. The end index operator ^ (hat operator) specifies that the index is relative to the end of the sequence. Let us see an example to understand this concept. Please have a look at the below example.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                "INDIA",
                "USA",
                "UK",
                "NZ",
                "CANADA",
                "CHINA",
                "NEPAL",
                "RUSIA",
                "SRILANKA",
                "INDONESIA"
            };

            Index i1 = 4;
            Console.WriteLine($"{countries[i1]}"); // Output: "CANADA"

            // Index 4 from end of the collection
            Index i2 = ^4;
            Console.WriteLine($"{countries[i2]}"); // Output: "NEPAL"
        }
    }
}
Output:

Index in C# 8

Please have a look at the below diagram which shows how Index works in C#. Here, you can see how the Index from start and how Index from the End works. As you can see, when we use 4 means Index from start and the value is CANADA and when we use ^4 means Index from End and the value is NEPAL which you can see in the output window.

Indices and Ranges in C# 8 with Examples

Now, let us understand the rules for indexes. Let us consider we have an array of countries. The 0 index is the same as countries[0]. The ^0 index is the same as countries[countries.Length]. Note that countries[^0] do throw an exception, just as countries[countries.Length] does. For any number n, the index ^n is the same as countries.Length – n. In the below example, we are using ^0 and it should throw an exception.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      //Index From End
                "INDIA",                //0                     //^10               
                "USA",                  //1                     //^9
                "UK",                   //2                     //^8
                "NZ",                   //3                     //^7
                "CANADA",               //4                     //^6
                "CHINA",                //5                     //^5
                "NEPAL",                //6                     //^4
                "RUSIA",                //7                     //^3
                "SRILANKA",             //8                     //^2
                "INDONESIA"             //9                     //^1
            };

            // Index 4 from end of the collection
            Index i2 = ^0;
            Console.WriteLine($"{countries[i2]}"); // Output: "Exception"
        }
    }
}
Output:

Indices and Ranges in C# 8 with Examples

Range in C# 8

The Range is a more natural syntax for specifying or accessing subranges in a sequence. The Range easily defines a sequence of data. It is a replacement for Enumerable.Range(), except that the Range, defines the start and stop points rather than start and count, and it helps you to write more readable code.

A range specifies the start and end of a range. The start of the range is inclusive, but the end of the range is exclusive, meaning the start is included in the range but the end isn’t included in the range. The range [0..^0] represents the entire range, just as [0..sequence.Length] represents the entire range.

Bounded Ranges in C#

In the bounded ranges, the lower bound (start index) and the upper bound (end index) are known or predefined.

Syntax: array[start..end] // Get items from start until end-1

Let us understand this with an example. The following example creates a subrange with the countries “INDIA”, “USA”, “UK” and “NZ”. It includes countries[0] through countries[3]. The element countries[4] aren’t in the range.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      
                "INDIA",                //0                                  
                "USA",                  //1                     
                "UK",                   //2                     
                "NZ",                   //3                     
                "CANADA",               //4                   
                "CHINA",                //5                    
                "NEPAL",                //6                    
                "RUSIA",                //7                    
                "SRILANKA",             //8                  
                "INDONESIA"             //9                     
            };

            var subCountries = countries[0..4]; //INDIA USA UK NZ
            foreach (var country in subCountries)
            {
                Console.WriteLine(country);
            }
        }
    }
}
Output:

Bounded Ranges in C#

Example:

Let us fetch the countries from the UK to CANADA.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      
                "INDIA",                //0                                  
                "USA",                  //1                     
                "UK",                   //2                     
                "NZ",                   //3                     
                "CANADA",               //4                   
                "CHINA",                //5                    
                "NEPAL",                //6                    
                "RUSIA",                //7                    
                "SRILANKA",             //8                  
                "INDONESIA"             //9                     
            };

            var subCountries = countries[2..5]; //UK NZ CANADA
            foreach (var country in subCountries)
            {
                Console.WriteLine(country);
            }
        }
    }
}

The following example creates a subrange with “RUSIA”, “SRILANKA”, and “INDONESIA”. It includes countries[^3] and countries[^1]. The end index countries[^0] aren’t included:

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      //Index From End
                "INDIA",                //0                     //^10               
                "USA",                  //1                     //^9
                "UK",                   //2                     //^8
                "NZ",                   //3                     //^7
                "CANADA",               //4                     //^6
                "CHINA",                //5                     //^5
                "NEPAL",                //6                     //^4
                "RUSIA",                //7                     //^3
                "SRILANKA",             //8                     //^2
                "INDONESIA"             //9                     //^1
            };

            var subCountries = countries[^3..^0]; //RUSIA SRILANKA INDONESIA
            foreach (var country in subCountries)
            {
                Console.WriteLine(country);
            }
        }
    }
}
Output:

Bounded Ranges in C# with Examples

Unbounded Ranges in C#

When the lower bound is omitted, it is interpreted to be zero, or the upper bound is omitted. It is interpreted to be the length of the receiving collection. The following example creates ranges that are open-ended for the start, end or both.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      //Index From End
                "INDIA",                //0                     //^10               
                "USA",                  //1                     //^9
                "UK",                   //2                     //^8
                "NZ",                   //3                     //^7
                "CANADA",               //4                     //^6
                "CHINA",                //5                     //^5
                "NEPAL",                //6                     //^4
                "RUSIA",                //7                     //^3
                "SRILANKA",             //8                     //^2
                "INDONESIA"             //9                     //^1
            };

            var allCountries = countries[..]; // contains INDIA through INDONESIA
            var firstPhrase = countries[..5]; // contains INDIA through CANADA
            var lastPhrase = countries[6..]; // contains NEPAL through INDONESIA

            Console.WriteLine("All Countries");
            foreach (var country in allCountries)
            {
                Console.Write($"{country} ");
            }
            Console.WriteLine("\nFirst Phrase Countries");
            foreach (var country in firstPhrase)
            {
                Console.Write($"{country} ");
            }
            Console.WriteLine("\nLast Phrase Countries");
            foreach (var country in lastPhrase)
            {
                Console.Write($"{country} ");
            }
        }
    }
}
Output:

Unbounded Ranges in C#

Ranges as variables in C#

We can also declare ranges as variables in C#. The following is the syntax:
Range phrase = 1..5;
The range. then can be used inside the [] characters as follows:
var subCountry= countries[phrase];

The following example shows how to use Ranges as variables in C#.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      //Index From End
                "INDIA",                //0                     //^10               
                "USA",                  //1                     //^9
                "UK",                   //2                     //^8
                "NZ",                   //3                     //^7
                "CANADA",               //4                     //^6
                "CHINA",                //5                     //^5
                "NEPAL",                //6                     //^4
                "RUSIA",                //7                     //^3
                "SRILANKA",             //8                     //^2
                "INDONESIA"             //9                     //^1
            };

            Range phrase = 1..5;
            var subCountries = countries[phrase];

            foreach (var country in subCountries)
            {
                Console.WriteLine($"{country} ");
            }
        }
    }
}
Output:

Ranges as variables in C#

Note: Not only do arrays support indices and ranges but you can also use indices and ranges with string, Span<T>, or ReadOnlySpan<T>.

Range with Strings in C#:

Ranges in C# allow creating substrings by using the indexer. Please have a look at the below example for a better understanding.

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var helloWorldStr = "Hello, World!";
            var hello = helloWorldStr[..5]; // Take 5 from the begin
            Console.WriteLine(hello); // Output: Hello
            var world = helloWorldStr[7..]; // Skip 7
            Console.WriteLine(world); // Output: World!
        }
    }
}
Output:

blank

Or you can write it like the following:

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var helloWorldStr = "Hello, World!";
            var hello = helloWorldStr[..5]; // Take 5 from the begin
            Console.WriteLine(hello); // Output: Hello
            var world = helloWorldStr[^6..]; // Take the last 6 characters from behind
            Console.WriteLine(world); // Output: World!
        }
    }
}
Output:

Indices and Ranges in C# 8 with Examples

Ranges Foreach loops in C#

Range with IEnumerable Example. Ranges implement IEnumerable<int>, which allows the iteration over a sequence of data

using System;
using System.Threading.Tasks;
namespace Csharp8Features
{
    class IndicesAndRanges
    {
        static async Task Main(string[] args)
        {
            var countries = new string[]
            {
                                        //Index From Start      //Index From End
                "INDIA",                //0                     //^10               
                "USA",                  //1                     //^9
                "UK",                   //2                     //^8
                "NZ",                   //3                     //^7
                "CANADA",               //4                     //^6
                "CHINA",                //5                     //^5
                "NEPAL",                //6                     //^4
                "RUSIA",                //7                     //^3
                "SRILANKA",             //8                     //^2
                "INDONESIA"             //9                     //^1
            };

            foreach (var firstFourCountries in countries[1..5])
            {
                Console.WriteLine($"{firstFourCountries} ");
            }
        }
    }
}
Output:

Indices and Ranges in C# 8 with Examples

In the next article, I am going to discuss Null-Coalescing Assignment ??= Operator in C# 8 with Examples. Here, in this article, I try to explain Indices and Ranges in C# 8 with Examples. I hope you enjoy this Indices and Ranges in C# 8 with Examples article.

Leave a Reply

Your email address will not be published.