Indices and range in C#

Indices and ranges

C# is still a popular computer language nowadays, it has a new released version every year and each release includes some syntax or features improvement. In this article, I introduce a new feature to you called indices and ranges. Before C# 8.0, there are no ranges attribute concept. In addition,  in order to get an element from array, The subscript index syntax is the only way to do this. "container[index]" to get the element and the index must be start from 0 and you cannot call -1 index in order to get the last element of container.

Therefore, getting the last or last second element from container,

However, for some advanced syntax computer language like python, you can access the last element or last two element through the following syntax. 

In other situation, if programmer want to get some elements from array, the old c# syntax is very inconvenient, you have to call three function in order to implement it.

Same as the getting last element in python, python also provides an easy way to get the sub-range in array.

Compared with the traditional syntax, python allow users manipulate array friendly. May be Microsoft know that it is not convenient to programmer for keeping the old way to manipulate array element. Therefore, it introduce new indices and ranges syntax in C# 8.0 

Operator

^ and .. are the operator to implement an easy way to manipulate array. 

^ operator specifies the index is start from end of an array elements.

.. operator specifies the start and end of a range of array.

For instance, the above traditional syntax can be simplify to the following syntax in C# 8

old syntax: string lastElement = arr[arr.Length - 1] ;
new syntax: string lastElement = arr[^0];

old syntax: string[] subRanges = arr.ToList().GetRange(1,2).ToArray();
new syntax: string[] subRanges = arr[1..2];

As you see, the syntax becomes more concise and easy to understand. 

Here are the further instance to show you how to use this feature.

1. Get third the last elements from array

old syntax: string element = arr[arr.Length - 3] ;

new syntax: string element = arr[^3];

For any number of ^number , the index ^number is same as the [arr.Length - number] syntax.

2. Get the sub-range of an array from second last element to last element.

old syntax: string[] subRange  = arr.ToList().GetRange(arr.Length-2, 2).ToArray();

new syntax: string[] subRange = arr[^2..^0]; or arr[^2..] ;

Type support

No doubt, array supports indices and ranges feature. As for other types, those types support and indexer or range explicitly also support this feature technically. For countable type, countable type means it has length or count function. It technically support this feature too. However, for some type, like List<T>. It only supports indices but not support ranges.  But String, Span<T> and ReadOnlySpan<T> supports indices and ranges both.

Practical Scenario

Usually, ranges and indices is used in data analysis task. When you are try to get a portion in a sequence and study their average, standard deviation or range min and range max. It is a friendly syntax to do this task. 

In this part, I use a moving average model to show you how to use this feature in practical case. 

Here is my procedure.

1. Generate a simply random walk dataset with 1 step movement 

2. Assign the window length and dataset to moving average class in order to get the moving average result

3. output the result to console. 

Furthermore, for a prettier output purpose, I use Spectre.Console library to output the data in table format. 

For further information about Spectre.Console, please go to https://spectreconsole.net/

This is a console program of dotnet core, I create a folder called MovingAverageIndotnet and run 

dotnet new console  Command to bootstrap a basic folder structure of console program. 

Then run the following command to install spectre console

dotnet add pakcage Spectre.Console 

After that, I create a "GenerateRandomWalkSequence" function in program.cs  It generates a random walk sequence with 1 step movement and accept  a parameter called "len" to indicate how long the sequence should the program generated.

To better encapsulated the programming logic, I create a  MovingAverage class to implement the core logic, 

here is the implementation

There are three member inside this class, they are 

_sequence: storing the data

_windowLen: defined the moving average window length 

_result: the moving average result

Two functions

1. Calculate // calculate the dataset moving average

2. GettingElement // getting the i position element from raw data and moving  average result. reverse parameter indicates the index start from the end of data. 

In calculate function, I use the .. operator in C#8 to get the subrange of data in order to calculate the moving average. 

In GettingElement function, I use ^ operator in C#8 to support getting element start from the end. 

Finally, in this example, I random 10 length raw data and calculate its' moving average using 2 window length.

Nevertheless, the raw data is generated by the program randomly. Therefore, the result should be different every time. The following is the result of this program when you run it.

Summary

In this post, I describe the different of indices and ranges feature before C# 8 and after C#8. The new feature is awesome and help us write the code more concise. In addition, I also tell you which type supports this awesome feature. Finally, I use a practical case Moving Average  to show you the implementation. I hope you enjoy the post.

For better understanding , please check out the example here: https://github.com/Isaac234517/MovingAverageInDotnet


Get the latest article from lab.

Please leave your email below.

Subscribe

Thank you for you subscription