Índices e intervalosIndices and ranges

Intervalos e índices fornecem uma sintaxe sucinta para acessar elementos únicos ou intervalos em uma sequência.Ranges and indices provide a succinct syntax for accessing single elements or ranges in a sequence.

Neste tutorial, você aprenderá a:In this tutorial, you'll learn how to:

  • Use a sintaxe para intervalos em uma sequência.Use the syntax for ranges in a sequence.
  • Compreenda as decisões de design para o início e o fim de cada sequência.Understand the design decisions for the start and end of each sequence.
  • Conheça cenários para os tipos Index e Range.Learn scenarios for the Index and Range types.

Suporte a idioma para intervalos e índicesLanguage support for indices and ranges

Esse suporte a idioma depende de dois novos tipos e de dois novos operadores:This language support relies on two new types and two new operators:

  • System.Index representa um índice em uma sequência.System.Index represents an index into a sequence.
  • O índice do operador ^end, que especifica que um índice é relativo ao final de uma sequência.The index from end operator ^, which specifies that an index is relative to the end of a sequence.
  • System.Range representa um subintervalo de uma sequência.System.Range represents a sub range of a sequence.
  • O operador ..Range, que especifica o início e o término de um intervalo como seus operandos.The range operator .., which specifies the start and end of a range as its operands.

Vamos começar com as regras para índices.Let's start with the rules for indices. Considere uma matriz sequence.Consider an array sequence. O índice 0 é o mesmo que sequence[0].The 0 index is the same as sequence[0]. O índice ^0 é o mesmo que sequence[sequence.Length].The ^0 index is the same as sequence[sequence.Length]. Observe que sequence[^0] gera uma exceção, assim como sequence[sequence.Length] faz.Note that sequence[^0] does throw an exception, just as sequence[sequence.Length] does. Para qualquer número n, o índice ^n é o mesmo que sequence[sequence.Length - n].For any number n, the index ^n is the same as sequence[sequence.Length - n].

string[] words = new string[]
{
                // index from start    index from end
    "The",      // 0                   ^9
    "quick",    // 1                   ^8
    "brown",    // 2                   ^7
    "fox",      // 3                   ^6
    "jumped",   // 4                   ^5
    "over",     // 5                   ^4
    "the",      // 6                   ^3
    "lazy",     // 7                   ^2
    "dog"       // 8                   ^1
};              // 9 (or words.Length) ^0

Você pode recuperar a última palavra com o índice ^1.You can retrieve the last word with the ^1 index. Adicione o código a seguir abaixo da inicialização:Add the following code below the initialization:

Console.WriteLine($"The last word is {words[^1]}");

Um intervalo especifica o início e o final de um intervalo.A range specifies the start and end of a range. Intervalos são exclusivos, o que significa que final não está incluído no intervalo.Ranges are exclusive, meaning the end is not included in the range. O intervalo [0..^0] representa todo o intervalo, assim como [0..sequence.Length] representa todo o intervalo.The range [0..^0] represents the entire range, just as [0..sequence.Length] represents the entire range.

O código a seguir cria um subintervalo com as palavras "quick", "brown" e "fox".The following code creates a subrange with the words "quick", "brown", and "fox". Ele inclui words[1] até words[3].It includes words[1] through words[3]. O elemento words[4] não está no intervalo.The element words[4] isn't in the range. Adicione o seguinte código ao mesmo método.Add the following code to the same method. Copie e cole-o na parte inferior da janela interativa.Copy and paste it at the bottom of the interactive window.

string[] quickBrownFox = words[1..4];
foreach (var word in quickBrownFox)
    Console.Write($"< {word} >");
Console.WriteLine();

O código a seguir cria um subintervalo com "lazy" e "dog".The following code creates a subrange with "lazy" and "dog". Ele inclui words[^2] e words[^1].It includes words[^2] and words[^1]. O índice final words[^0] não está incluído.The end index words[^0] isn't included. Adicione o seguinte código também:Add the following code as well:

string[] lazyDog = words[^2..^0];
foreach (var word in lazyDog)
    Console.Write($"< {word} >");
Console.WriteLine();

Os exemplos a seguir criam intervalos abertos para o início, fim ou ambos:The following examples create ranges that are open ended for the start, end, or both:

string[] allWords = words[..]; // contains "The" through "dog".
string[] firstPhrase = words[..4]; // contains "The" through "fox"
string[] lastPhrase = words[6..]; // contains "the, "lazy" and "dog"
foreach (var word in allWords)
    Console.Write($"< {word} >");
Console.WriteLine();
foreach (var word in firstPhrase)
    Console.Write($"< {word} >");
Console.WriteLine();
foreach (var word in lastPhrase)
    Console.Write($"< {word} >");
Console.WriteLine();

Você também pode declarar intervalos ou índices como variáveis.You can also declare ranges or indices as variables. A variável então pode ser usada dentro dos caracteres [ e ]:The variable can then be used inside the [ and ] characters:

Index the = ^3;
Console.WriteLine(words[the]);
Range phrase = 1..4;
string[] text = words[phrase];
foreach (var word in text)
    Console.Write($"< {word} >");
Console.WriteLine();

O exemplo a seguir mostra muitos dos motivos para essas escolhas.The following sample shows many of the reasons for those choices. Modifique x, y e z para tentar combinações diferentes.Modify x, y, and z to try different combinations. Quando você testar, use valores em que x é menor que y e y é menor que z para as combinações válidas.When you experiment, use values where x is less than y, and y is less than z for valid combinations. Adicione o seguinte código a um novo método.Add the following code in a new method. Tente usar combinações diferentes:Try different combinations:

int[] numbers = Enumerable.Range(0, 100).ToArray();
int x = 12;
int y = 25;
int z = 36;

Console.WriteLine($"{numbers[^x]} is the same as {numbers[numbers.Length - x]}");
Console.WriteLine($"{numbers[x..y].Length} is the same as {y - x}");

Console.WriteLine("numbers[x..y] and numbers[y..z] are consecutive and disjoint:");
Span<int> x_y = numbers[x..y];
Span<int> y_z = numbers[y..z];
Console.WriteLine($"\tnumbers[x..y] is {x_y[0]} through {x_y[^1]}, numbers[y..z] is {y_z[0]} through {y_z[^1]}");

Console.WriteLine("numbers[x..^x] removes x elements at each end:");
Span<int> x_x = numbers[x..^x];
Console.WriteLine($"\tnumbers[x..^x] starts with {x_x[0]} and ends with {x_x[^1]}");

Console.WriteLine("numbers[..x] means numbers[0..x] and numbers[x..] means numbers[x..^0]");
Span<int> start_x = numbers[..x];
Span<int> zero_x = numbers[0..x];
Console.WriteLine($"\t{start_x[0]}..{start_x[^1]} is the same as {zero_x[0]}..{zero_x[^1]}");
Span<int> z_end = numbers[z..];
Span<int> z_zero = numbers[z..^0];
Console.WriteLine($"\t{z_end[0]}..{z_end[^1]} is the same as {z_zero[0]}..{z_zero[^1]}");

Suporte de tipo para índices e intervalosType support for indices and ranges

Se um tipo fornecer um indexador com um parâmetro Index ou Range, ele dará suporte explicitamente a índices ou intervalos, respectivamente.If a type provides an indexer with an Index or Range parameter, it explicitly supports indices or ranges respectively.

Um tipo é contável se tiver uma propriedade chamada Length ou Count com um getter acessível e um tipo de retorno de int.A type is countable if it has a property named Length or Count with an accessible getter and a return type of int. Um tipo com contagem que não dá suporte explicitamente a índices ou intervalos pode fornecer um suporte implícito para eles.A countable type that doesn't explicitly support indices or ranges may provide an implicit support for them. Para obter mais informações, consulte as seções suporte ao índice implícito e suporte de intervalo implícito da Nota de proposta de recurso.For more information, see the Implicit Index support and Implicit Range support sections of the feature proposal note.

Por exemplo, os seguintes tipos .NET oferecem suporte a índices e intervalos: Array, String, Span<T> e ReadOnlySpan<T>.For example, the following .NET types support both indices and ranges: Array, String, Span<T>, and ReadOnlySpan<T>. O List<T> dá suporte a índices, mas não dá suporte a intervalos.The List<T> supports indices but doesn't support ranges.

Cenários para índices e intervalosScenarios for indices and ranges

Você muitas vezes usará intervalos e índices quando quiser executar uma análise no subintervalo de uma sequência inteira.You'll often use ranges and indices when you want to perform some analysis on subrange of an entire sequence. A nova sintaxe é mais clara para ler exatamente quais subintervalo está envolvido.The new syntax is clearer in reading exactly what subrange is involved. A função local MovingAverage usa um Range como seu argumento.The local function MovingAverage takes a Range as its argument. O método então enumera apenas esse intervalo ao calcular o mínimo, máximo e média.The method then enumerates just that range when calculating the min, max, and average. Experimente o seguinte código em seu projeto:Try the following code in your project:

int[] sequence = Sequence(1000);


for(int start = 0; start < sequence.Length; start += 100)
{
    Range r = start..(start+10);
    var (min, max, average) = MovingAverage(sequence, r);
    Console.WriteLine($"From {r.Start} to {r.End}:    \tMin: {min},\tMax: {max},\tAverage: {average}");
}

for (int start = 0; start < sequence.Length; start += 100)
{
    Range r = ^(start + 10)..^start;
    var (min, max, average) = MovingAverage(sequence, r);
    Console.WriteLine($"From {r.Start} to {r.End}:  \tMin: {min},\tMax: {max},\tAverage: {average}");
}

(int min, int max, double average) MovingAverage(int[] subSequence, Range range) =>
    (
        subSequence[range].Min(),
        subSequence[range].Max(),
        subSequence[range].Average()
    );

int[] Sequence(int count) =>
    Enumerable.Range(0, count).Select(x => (int)(Math.Sqrt(x) * 100)).ToArray();

Baixe o código concluído no repositório dotnet/samples.You can download the completed code from the dotnet/samples repository.