Thursday, 26 July 2018

Ranges in C# 8.0


Ranges

This feature is about delivering two new operators (Index operator ‘^’ and range operator ‘..’) that allow constructing System.Index and System.Range objects and using them to index or slice collections at runtime. The new operators are syntactic sugar and making your code more clean and readable. The code for the operator index ^ is implemented in System.Index and for the range ‘..’ in System.Range.

System.Index
Excellent way toindex a collection from the ending.

Example
var lastItem = array[^1]; this code equivalent to: var lastItem = array[collection.Count-1];
System.Range

Ranges way to access "ranges" or "slices" of collections. This will help you to avoid LINQ and making your code compact and more readable. You can compare this feature with Ranges in F#.


New style
Old style
var thirdItem = array [2]; 
// Code behind: array [2]
var thirdItem = array [2]; 
var lastItem = array [^1];
// Code Behind: [^1] = new Index(1, true); true = bool fromEnd 
var lastItem = array [array.Count -1];
var lastItem = array.Last; // LINQ
var subCollection = array[2..^5]; // Output: 2, 3, 4, 5
// Code Behind: Range.Create(2, new Index(5, true)); as you see here we have used the both operators! Range and Index. The Range is for the operator … and the index is for the operator ^. Means skip until the index 2 from the begin and ^5 means ignore the first 5 elements from behind.
var subCollection = array.ToList().GetRange(2, 4);
or with LINQ
var subCollection = array.Skip(2).Take(4);


Examples

Consider the following array:

var array = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Now we cut a slice view from this array as below:

var slice= array[2..5];


Value: 2 3 4

We can access the slice values with the following indexes:


Index 0 1 2

Note: the start index is inclusive (included to the slice), and the end index is exclusive (excluded from the slice).var slice1 = array [4..^2]; // Range.Create(4, new Index(2, true))

and the slice1 will be of type Span<int>. [4..^2] Skip from the begin until the index 4 and skip 2 from the ending.Output: 4, 5, 6, 7, 8 var slice2 = array [..^3]; // Range.ToEnd(new Index(3, true)) Output: 0, 1, 2, 3, 4, 5, 6, 7 var slice3 = array [2..]; // Range.FromStart(2) Output: 2, 3, 4, 5, 6, 7, 8,9, 10 var slice4 = array[..]; // array[Range.All] Output: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10


Bounded Ranges

In the bounded ranges, the lower bound (start index) and the upper bound(end index) are known or predefined.array[start..end] // Get items from start-1 until end-1 array[start..end:step] // Get items from start-1 until end-1 by step


The above Range syntax (step at end) is inspiredfrom Python. Python supports the following syntax(lower:upper:step), with :stepbeing optional and :1 by default, but there are some wishes in the community to use the F# syntax (lower..step..upper).

Range syntax in F#.


array { 5 .. 2 .. 20 } // where 2 = step [start .. step .. end]

Output:


5 7 9 11 13 15 17 19
Example for the bounded rangesvar array = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; var subarray = array[3..5]; // The selected items: 3, 4


The code above is equal to array.ToList().GetRange(3, 2);.If you compare array.ToList().GetRange(3, 2); with array[3..5] you can see that the new style is cleanerand more human readable.

There is a feature request to use the Range in the “if” statement or with the pattern matching as described below:

With “in” operatorvar anyChar = 'b'; if (anyChar in 'a'..'z') { Console.WriteLine($"The letter {anyChar} in range!"); } Output: The letter b in range!

Range Pattern is one of the new proposed pattern matching which can be used to produce simple range checks. Range Pattern will allow you to use the range operator ‘..’ in the select case" statement (switch).switch (anyChar) { case in 'a'..'z' => Console.WriteLine($“The letter {anyChar} in range!”), case in '!'..'+' => Console.WriteLine($“Something else!”), } Output: The letter b in range!

It is worth to mention that not everyone happy by using the “in” operator in Ranges. The community is divided between using “in” or “is”;


Unbounded Ranges


When the lower bound is omitted, it's interpreted to be zeroor the upper bound is omitted, it's interpreted to be the length of the receiving collection.
Examplesarray[start..] // Get items start-1 with the rest of the array array[..end] // Get items from the beginning until end-1 array[..] // A Get the whole array

Positive Boundsvar fiveToEnd = 5..; // Equivalent to Range.From(5) i.e. missing upper bound var startToTen = ..1; // Equivalent to Range.ToEnd(1). Missing lower bound. Result: 0, 1 var everything = ..; // Equivalent to Range.All. Missing upper and lower bound. Result: 0..Int.Max var everything = [5..11]; // Equivalent to Range.Create(5, 11) var collection = new [] { 'a', 'b', 'c' }; collection[2..]; // Result chars: c collection[..2]; // Result chars: a, b collection[..]; // Result chars: a, b, c


No comments:

Post a Comment

SQL Audits

1. sys.server_audits What it is: Lists all server-level audit objects . An audit is the top-level object that defines: Where to wri...