Índices e intervalos em arrays no C#

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 StartClique 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 ExpertClique 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!