详解c#索引(Index)和范围(Range)

范围和索引为访问序列中的单个元素或范围提供了简洁的语法。

在本教程中,你将了解:

  • 对某个序列中的范围使用该语法。
  • 了解每个序列开头和末尾的设计决策。
  • 了解 Index 和 Range 类型的应用场景。

对索引和范围的语言支持

此语言支持依赖于两个新类型和两个新运算符:

  • System.Index 表示一个序列索引。
  • 来自末尾运算符 ^ 的索引,指定一个索引与序列末尾相关。
  • System.Range 表示序列的子范围。
  • 范围运算符 ..,用于指定范围的开始和末尾,就像操作数一样。

让我们从索引规则开始。 请考虑数组 sequence0 索引与 sequence[0] 相同。 ^0 索引与 sequence[sequence.Length] 相同。 表达式 sequence[^0] 不会引发异常,就像 sequence[sequence.Length] 一样。 对于任何数字 n,索引 ^nsequence[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

可以使用 ^1 索引检索最后一个词。 在初始化下面添加以下代码:

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

范围指定范围的开始和末尾。 范围是排除的,也就是说“末尾”不包含在范围内。 范围 [0..^0] 表示整个范围,就像 [0..sequence.Length] 表示整个范围。
以下代码创建了一个包含单词“quick”、“brown”和“fox”的子范围。 它包括 words[1] 到 words[3]。 元素 words[4] 不在该范围内。 将以下代码添加到同一方法中。 将其复制并粘贴到交互式窗口的底部。

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

以下代码使用“lazy”和“dog”返回范围。 它包括 words[^2]words[^1]。 结束索引 words[^0] 不包括在内。 同样添加以下代码:

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

下面的示例为开始和/或结束创建了开放范围:

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();

还可以将范围或索引声明为变量。 然后可以在 [ 和 ] 字符中使用该变量:

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();

下面的示例展示了使用这些选项的多种原因。 请修改 x、y 和 z 以尝试不同的组合。 在进行实验时,请使用 x 小于 y且 y 小于 z 的有效组合值。 在新方法中添加以下代码。 尝试不同的组合:

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]}");

详解c#索引(Index)和范围(Range)

扫一扫手机访问