Os arrays são estruturas fundamentais em C#, permitindo armazenar e manipular coleções de elementos do mesmo tipo. A partir do C# 8.0, novas funcionalidades foram introduzidas para tornar o trabalho com arrays ainda mais eficiente. Neste artigo vamos explorar desde os índices tradicionais até as últimas novidades como índices negativos com o operador “^” e intervalos “(..)” para criar subarrays.
Índices tradicionais em arrays
Nos arrays, os índices são utilizados para acessar elementos individuais. Eles começam do zero, ou seja, o primeiro elemento está no índice 0, o segundo no índice 1, e assim por diante.
int[] numeros = { 10, 20, 30, 40, 50 };
Console.WriteLine(numeros[0]);
Console.WriteLine(numeros[2]);
Se você tentar acessar um índice fora dos limites do array (numeros[5]), uma exceção “IndexOutOfRangeException” será lançada.
Índices negativos com o operador ^
Com o C# 8.0, foi introduzido o operador “^” para trabalhar com índices relativos ao final do array. Isso simplifica o acesso ao último elemento ou a elementos próximos ao fim.
int[] numeros = { 10, 20, 30, 40, 50 };
Console.WriteLine(numeros[^1]);
Console.WriteLine(numeros[^2]);
Aqui, o número após o operador “^” indica a posição a ser acessada de trás para frente no array. No exemplo acima, o console exibirá os valores 50 (último elemento) e 40 (penúltimo elemento).
Intervalos com o operador ..
O operador “..” permite criar subarrays (fatias ou slices) de maneira concisa. Ele utiliza dois índices, um inicial e um final, separados por “..”.
Regras para usar o operador ..
Ao definir um intervalo como [inicial..final], você especifica onde o intervalo começa e termina.
int[] numeros = { 10, 20, 30, 40, 50 };
int[] fatia1 = numeros[1..3];
Console.WriteLine(string.Join(", ", fatia1));
Nesse exemplo, a fatia inclui os elementos “numeros[1]” (20) e “numeros[2]” (30), mas exclui o elemento “numeros[3]”.
Se você omitir o índice inicial (..final), o intervalo começa no primeiro elemento do array e vai até o índice especificado (não incluído).
int[] fatia2 = numeros[..3];
Console.WriteLine(string.Join(", ", fatia2));
O intervalo “[..3]” inclui os elementos “numeros[0]”, “numeros[1]” e “numeros[2]”.
Se você omitir o índice final (inicial..), o intervalo vai do índice inicial especificado até o último elemento do array.
int[] fatia3 = numeros[2..];
Console.WriteLine(string.Join(", ", fatia3));
Nesse caso, o intervalo “[2..]” inclui todos os elementos a partir de “numeros[2]” até o final do array.
Se você omitir tanto o índice inicial quanto o final (..), o intervalo abrange o array inteiro. Essa sintaxe equivale a criar uma cópia completa do array.
int[] fatiaCompleta = numeros[..];
Console.WriteLine(string.Join(", ", fatiaCompleta));
Combinação com o operador ^
O operador “^” pode ser combinado com “..” para criar intervalos relativos ao final do array. Isso é útil para trabalhar com os últimos elementos de uma coleção.
int[] ultimos = numeros[^3..];
Console.WriteLine(string.Join(", ", ultimos));
O [ ^3.. ] começa no terceiro elemento a partir do final e vai até o final do array. A saída será 30, 40, 50.
int[] semOsUltimos = numeros[..^2];
Console.WriteLine(string.Join(", ", semOsUltimos));
O [ ..^2 ] vai do início do array até dois elementos antes do final. O resultado será 10, 20, 30.
Combinando intervalos com métodos de extensão
Uma outra possibilidade do C# é a de combinar intervalos com métodos de extensão como “Where”, “Select”, e outros disponíveis no LINQ. Isso permite criar filtros e transformações dinâmicas diretamente sobre fatias de arrays.
Você pode usar o operador “..” para criar um subarray e aplicar um filtro dinâmico com o método “Where”:
int[] numeros = { 10, 15, 20, 25, 30 };
var pares = numeros[1..4].Where(n => n % 2 == 0);
Console.WriteLine(string.Join(", ", pares));
O intervalo “[1..4]” seleciona os elementos do índice 1 ao índice 3 (15, 20, 25). Após isso, o método “Where” filtra os elementos que são pares. A saída resulta em 20.
Além de filtrar, você pode transformar os valores de um intervalo utilizando o método “Select”:
int[] numeros = { 10, 15, 20, 25, 30 };
var dobrados = numeros[2..].Select(n => n * 2);
Console.WriteLine(string.Join(", ", dobrados));
Neste exemplo, o intervalo “[2..]” seleciona todos os elementos a partir do índice 2 (20, 25, 30). O método “Select” aplica a transformação “n * 2” a cada elemento do intervalo.
O resultado será uma nova lista com os números 40, 50, 60 armazenados na variável “dobrados”.
Acelere a sua carreira conosco!
Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET Start: Clique aqui
Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET Expert: Clique aqui
Conclusão
Índices e intervalos negativos em C# oferecem novas possibilidades para manipular arrays e coleções de forma simples e eficiente. Esses recursos tornam o código mais expressivo, eliminando a necessidade de cálculos manuais de índice. Além disso, intervalos e índices negativos podem ser combinados com outros recursos modernos de C# para criar soluções robustas e claras.
Explore essas funcionalidades em seus projetos e veja como elas podem simplificar suas implementações!