Indizes und BereicheIndices and ranges

Bereiche und Indizes bieten eine prägnante Syntax für den Zugriff auf einzelne Elemente oder Bereiche in einer Sequenz.Ranges and indices provide a succinct syntax for accessing single elements or ranges in a sequence.

In diesem Tutorial lernen Sie, wie die folgenden Aufgaben ausgeführt werden:In this tutorial, you'll learn how to:

  • Verwenden Sie die Syntax für Bereiche in einer Sequenz.Use the syntax for ranges in a sequence.
  • Lernen Sie die Entwurfsentscheidungen für Start und Ende jeder Sequenz kennen.Understand the design decisions for the start and end of each sequence.
  • Lernen Sie Szenarien für die Typen Index und Range kennen.Learn scenarios for the Index and Range types.

Sprachunterstützung für Indizes und BereicheLanguage support for indices and ranges

Diese Sprachunterstützung basiert auf zwei neuen Typen und zwei neuen Operatoren:This language support relies on two new types and two new operators:

  • System.Index: Stellt einen Index in einer Sequenz dar.System.Index represents an index into a sequence.
  • Der Index vom Endeoperator ^, der angibt, dass ein Index relativ zum Ende einer Sequenz ist.The index from end operator ^, which specifies that an index is relative to the end of a sequence.
  • System.Range: Stellt einen Unterbereich einer Sequenz dar.System.Range represents a sub range of a sequence.
  • Der Bereichsoperator .., der den Beginn und das Ende eines Bereichs als seine Operanden angibt.The range operator .., which specifies the start and end of a range as its operands.

Beginnen wir mit den Regeln für Indizes.Let's start with the rules for indices. Betrachten Sie einen Array sequence.Consider an array sequence. Der 0-Index entspricht sequence[0].The 0 index is the same as sequence[0]. Der ^0-Index entspricht sequence[sequence.Length].The ^0 index is the same as sequence[sequence.Length]. Beachten Sie, dass sequence[^0] genau wie sequence[sequence.Length] eine Ausnahme auslöst.Note that sequence[^0] does throw an exception, just as sequence[sequence.Length] does. Für eine beliebige Zahl n ist der Index ^n identisch mit 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

Sie können das letzte Wort mit dem ^1-Index abrufen.You can retrieve the last word with the ^1 index. Fügen Sie unter der Initialisierung folgenden Code hinzu:Add the following code below the initialization:

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

Ein Bereich gibt den Beginn und das Ende eines Bereichs an.A range specifies the start and end of a range. Bereiche sind exklusiv, d.h. das Ende ist nicht im Bereich enthalten.Ranges are exclusive, meaning the end is not included in the range. Der Bereich [0..^0] stellt ebenso wie [0..sequence.Length] den gesamten Bereich dar.The range [0..^0] represents the entire range, just as [0..sequence.Length] represents the entire range.

Der folgende Code erzeugt einen Teilbereich mit den Worten „quick“, „brown“ und „fox“.The following code creates a subrange with the words "quick", "brown", and "fox". Er enthält words[1] bis words[3].It includes words[1] through words[3]. Das Element words[4] befindet sich nicht im Bereich.The element words[4] isn't in the range. Fügen Sie derselben Methode den folgenden Code hinzu.Add the following code to the same method. Kopieren Sie ihn, und fügen Sie ihn unten in das interaktive Fenster ein.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();

Der folgende Code erzeugt einen Teilbereich mit „lazy“ und „dog“.The following code creates a subrange with "lazy" and "dog". Dazu gehören words[^2] und words[^1].It includes words[^2] and words[^1]. Der Endindex words[^0] ist nicht enthalten.The end index words[^0] isn't included. Fügen Sie den folgenden Code auch hinzu:Add the following code as well:

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

Die folgenden Beispiele erstellen Bereiche, die am Anfang, am Ende und auf beiden Seiten offen sind: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();

Sie können Bereiche oder Indizes auch als Variablen deklarieren.You can also declare ranges or indices as variables. Die Variable kann dann innerhalb der Zeichen [ und ] verwendet werden: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();

Das folgende Beispiel zeigt viele der Gründe für diese Auswahl.The following sample shows many of the reasons for those choices. Ändern Sie x, y und z, um verschiedene Kombinationen zu testen.Modify x, y, and z to try different combinations. Verwenden Sie beim Experimentieren Werte, wo x kleiner ist als y und y kleiner als z für gültige Kombinationen.When you experiment, use values where x is less than y, and y is less than z for valid combinations. Fügen Sie den folgenden Code in einer neuen Methode hinzu.Add the following code in a new method. Probieren Sie verschiedene Kombinationen aus: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]}");

Typunterstützung für Indizes und BereicheType support for indices and ranges

Wenn ein Typ einen Indexer mit einem Index- oder Range-Parameter bereitstellt, unterstützt er explizit Indizes bzw. Bereiche.If a type provides an indexer with an Index or Range parameter, it explicitly supports indices or ranges respectively.

Ein Typ ist zählbar, wenn er über eine Eigenschaft mit dem Namen Length oder Count mit einem zugreifbaren Getter und einem Rückgabetyp von int verfügt.A type is countable if it has a property named Length or Count with an accessible getter and a return type of int. Ein zählbarer Typ, der Indizes oder Bereiche nicht explizit unterstützt, kann implizite Unterstützung dafür bieten.A countable type that doesn't explicitly support indices or ranges may provide an implicit support for them. Weitere Informationen finden Sie in den Abschnitten Implizite Indexunterstützung und Implizite Bereichsunterstützung der Featurevorschläge.For more information, see the Implicit Index support and Implicit Range support sections of the feature proposal note.

Beispielsweise unterstützen die folgenden .NET-Typen Indizes und Bereiche: Array, String, Span<T> und ReadOnlySpan<T>.For example, the following .NET types support both indices and ranges: Array, String, Span<T>, and ReadOnlySpan<T>. List<T> unterstützt Indizes, jedoch keine Bereiche.The List<T> supports indices but doesn't support ranges.

Szenarien für Indizes und BereicheScenarios for indices and ranges

Sie verwenden häufig Bereiche und Indizes, wenn Sie eine Analyse eines Teilbereichs einer vollständigen Sequenz ausführen möchten.You'll often use ranges and indices when you want to perform some analysis on subrange of an entire sequence. Aus der neuen Syntax lässt sich klarer herauslesen, welcher Teilbereich beteiligt ist.The new syntax is clearer in reading exactly what subrange is involved. Die lokale Funktion MovingAverage nimmt einen Range als Argument entgegen.The local function MovingAverage takes a Range as its argument. Die Methode listet dann genau diesen Bereich bei der Berechnung von Minimum, Maximum und Durchschnitt auf.The method then enumerates just that range when calculating the min, max, and average. Probieren Sie den folgenden Code in Ihrem Projekt aus: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();

Sie können den fertig gestellten Code aus dem Repository dotnet/samples herunterladen.You can download the completed code from the dotnet/samples repository.