C# 8.0 – Specification – Index and Ranges
Índice general – C# 8.0 – Specification
En esta entrada, vamos a ver una de las nuevas características de C# 8.0, denominada Index and Ranges o Índices y Rangos.
Antes de entrar en los ejemplos prácticos de estas nuevas características tengamos en cuenta que estas características son posibles gracias a dos nuevos operadores incluidos en C#.
Se trata del operador ^ y del operador ..
Estos operadores se pueden utilizar de forma separada o conjunta.
El soporte de estos dos operadores se logra a través de dos nuevas estructuras incorporadas en el lenguaje, System.Index y System.Range, ambas pertenecientes a System.Runtime.dll y netstandard.dll.
Index representa en su caso un índice (como indica su nombre) dentro de una secuencia (operador ^).
Range por su parte, representa un sub rango dentro de una secuencia (operador ..).
Para entenderlos mejor, voy a explicar de forma práctica y con más profundidad cómo funcionan y qué nos puede aportar cada uno de ellos.
Index
Para Index, vamos a utilizar el operador ^
Supongamos el siguiente array de datos:
private static string[] _myArray = { "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten" };
Imaginemos que queremos obtener el primer elemento y el último de ese array.
Obtener el primer elemento es realmente sencillo: _myArray[0]
Obtener el último requerirá conocer el número de elementos y acceder al último:
_myArray[_myArray.Count() - 1]
Para hacer compatible esta forma de acceder a los elementos del array, podemos utilizar Index también.
Bastará con declarar el primer elemento y el último como tipos Index.
Index first = 0; Index last = ^1;
Para acceder a sus elementos, deberemos hacer algo así como:
_myArray[first] _myArray[last]
Como podemos apreciar en este ejemplo, el uso es cómodo aunque muy similar al tradicional.
Range
Para Range, vamos a utilizar el operador ..
Suponiendo el mismo array de datos que teníamos para Index, imaginemos que queremos obtener todos los elementos del array a partir de la posición 2 del mismo, es decir, el tercer elemento y así hasta el final.
Para ello, podemos utilizar la siguiente instrucción de código:
_myArray[2..]
Supongo que lo tenemos todos en mente, pero conviene recordar que en C# el índice de elementos de un array empieza por 0, por lo que tenemos que tener en consideración que los índices del array son 0, 1, 2…, y por lo tanto el 2 es el tercer elemento.
Así que en este ejemplo obtendríamos: Three, Four, Five, Six, Seven, Eight, Nine, Ten
Index and Ranges
Además de poder utilizar de forma independiente los operadores de Index y Range, también podemos utilizar ambos operadores de forma conjunta.
Reutilizando el array de datos que vimos inicialmente, vamos a escribir el siguiente código:
_myArray[^4..]
Como vemos aquí, estamos utilizando ambos operadores.
En este caso, indicamos que nos vamos a situar al final del array y vamos a recuperar los últimos cuatro elementos del mismo (^4).
De esta manera, obtendremos:
Seven, Eight, Nine, Ten
Sin embargo, no sólo tenemos la posibilidad de trabajar con arrays.
También podemos trabajar con cadenas de texto, y podemos obtener de ella una parte de la misma.
Imaginemos el siguiente texto declarado como:
var message = "Hello, this is a sample text";
Si escribimos la siguiente instrucción de código:
message[^11..^0]
Estaremos obteniendo el texto: «sample text»
En este caso, nos situaremos al final de la cadena de texto y nos posicionaremos 11 caracteres atrás.
Desde allí recuperaremos todos los caracteres hasta el final.
Es como podemos ver, una forma muy similar de acceder a un elemento.
De hecho, podríamos haber indicado lo mismo de esta otra forma:
message[^11..]
Ahora bien, podríamos dar una vuelta de tuerca a Index y Ranges y pensar un poco en objetos.
Partamos de una clase inicial:
private class Person { public int Id { get; set; } public string Name { get; set; } }
Creemos un array de tipo Person y agregemos algunos elementos al array.
Por ejemplo:
var people = new Person[] { new Person() { Id = 0, Name = "Peter" }, new Person() { Id = 1, Name = "Mary" }, new Person() { Id = 2, Name = "John" }, new Person() { Id = 3, Name = "Anna" }, new Person() { Id = 4, Name = "Jonas" }, new Person() { Id = 5, Name = "Rose" }, new Person() { Id = 6, Name = "Lya" } };
Y escribamos este código:
foreach (var person in people[2..^2]) { Console.WriteLine($"Name: '{person.Name}'"); }
Aquí nos estaremos situando en el segundo elemento (recordemos que los íncides en arrays en C# empiezan por 0, por lo que en realidad es el tercer elemento correspondiente a «John»).
Y recogeremos todos los elementos menos los dos últimos.
Así que el resultado que obtendremos será:
John, Anna, Jonas
Como podemos apreciar, Index y Range nos ofrece una forma más sencilla y rápida de acceder a elementos pertenecientes a una matriz o array.
Nos evita recorrer los elementos para acceder a los últimos (si es nuestra necesidad), y nos permite realizar accesos directos a esos elementos.
Todo esto con una mejora de rendimiento y eficiencia dentro de nuestras aplicaciones, algo que siempre viene bien.
Se trata por lo tanto de una característica bastante útil, si bien, la forma tradicional que estábamos utilizando para acceder a elementos de la matriz o array sigue siendo válida.
Happy Coding!