 范围运算符
范围运算符
  在 C# 8.0 中,引入了一个新的范围操作符 ..,用于在数组、列表和字符串等类型中选取一个范围。该操作符的左操作数表示范围的起始位置(包含该位置),右操作数表示范围的结束位置(不包含该位置),两者中间用 .. 连接。
下面将详细介绍 .. 操作符的各种用法及其示例。
# 选取数组中的范围
# 选取从起始位置开始的一段范围
以下示例中,我们定义了一个整数数组 numbers,然后使用 .. 操作符选取从起始位置开始的前三个元素,并将其存储在 subset 数组中。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int amountToTake = 3;
int[] subset = numbers[0..amountToTake];
Display(subset);  // output: 0 10 20
# 选取从指定位置开始的一段范围
以下示例中,我们定义了一个整数数组 numbers,然后使用 .. 操作符选取从第二个位置(索引为 1)开始的前三个元素,并将其存储在 subset 数组中。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int start = 1;
int amountToTake = 3;
int[] subset = numbers[start..(start + amountToTake)];
Display(subset);  // output: 10 20 30
# 选取从结尾位置开始的一段范围
以下示例中,我们定义了一个整数数组 numbers,然后使用 .. 操作符选取从结尾位置开始的前三个元素,并将其存储在 subset 数组中。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int amountToTakeFromEnd = 3;
int[] subset = numbers[^amountToTakeFromEnd..];
Display(subset);  // output: 20 30 40
# 选取除了起始位置和结尾位置之外的一段范围
以下示例中,我们定义了一个整数数组 numbers,然后使用 .. 操作符选取除了起始位置和结尾位置之外的一段范围,并将其存储在 inner 数组中。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int margin = 1;
int[] inner = numbers[margin..^margin];
Display(inner);  // output: 10 20 30 40
# 选取字符串中的范围
以下示例中,我们定义了一个字符串 line,然后使用 .. 操作符选取从倒数第五个字符到结尾位置的一段范围,并将其存储在 end 变量中。
string line = "one two three";
int amountToTakeFromEnd = 5;
Range endIndices = ^amountToTakeFromEnd..^0;
string end = line[endIndices];
Console.WriteLine(end);  // output: three
# 部分省略操作数
可以部分省略 .. 操作符的左操作数或右操作数来获取一个开放式范围。
# 省略左操作数
省略左操作数 a,可以获取从起始位置开始的开放式范围,等价于 a..^0。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int[] subset = numbers[..3];
Display(subset);  // output: 0 10 20
# 省略右操作数
省略右操作数 b,可以获取从结尾位置开始的开放式范围,等价于 0..b。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int[] subset = numbers[^3..];
Display(subset);  // output: 30 40 50
# 省略左右操作数
省略左右操作数 a 和 b,可以获取整个序列的开放式范围,等价于 0..^0。
int[] numbers = new[] { 0, 10, 20, 30, 40, 50 };
int[] subset = numbers[..];
Display(subset);  // output: 0 10 20 30 40 50
表达集合范围的各种方法:
| 范围运算符表达式 | 说明 | 
|---|---|
| .. | 集合中的所有值。 | 
| ..end | 从开头到 end(不含)的值。 | 
| start.. | 从 start(含)到结尾的值。 | 
| start..end | 从 start(含)到 end(不含)的值。 | 
| ^start.. | 从 start(含)到倒计数结尾的值。 | 
| ..^end | 从开头到 end(不含,倒计数)的值。 | 
| start..^end | 从 start(含)到 end(不含,倒计数)的值。 | 
| ^start..^end | 从 start(含)到 end(不含),均为倒计数。 | 
以下示例演示了使用上表中所有范围的效果:
int[] oneThroughTen =
{
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
Write(oneThroughTen, ..);
Write(oneThroughTen, ..3);
Write(oneThroughTen, 2..);
Write(oneThroughTen, 3..5);
Write(oneThroughTen, ^2..);
Write(oneThroughTen, ..^3);
Write(oneThroughTen, 3..^4);
Write(oneThroughTen, ^4..^2);
static void Write(int[] values, Range range) =>
    Console.WriteLine($"{range}:\t{string.Join(", ", values[range])}");
// Sample output:
//      0..^0:      1, 2, 3, 4, 5, 6, 7, 8, 9, 10
//      0..3:       1, 2, 3
//      2..^0:      3, 4, 5, 6, 7, 8, 9, 10
//      3..5:       4, 5
//      ^2..^0:     9, 10
//      0..^3:      1, 2, 3, 4, 5, 6, 7
//      3..^4:      4, 5, 6
//      ^4..^2:     7, 8
# 结论
.. 操作符是 C# 8.0 中的一个新特性,可以方便地选取数组、列表和字符串等类型中的一段范围。该操作符不仅可以指定起始位置和结束位置,还可以通过省略操作数来获取开放式范围。
