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
Please leave your email below.