C# 切片语法糖(范围和索引)
语法
索引
^ 末尾运算符
代表尾部索引,例:
nums[^1]:取最后 1 个元素nums[^1]:取倒数第 2 个元素
范围
.. 范围运算符
代表左闭右开范围,例:
nums[1..5]:取数组索引 [1,5) 这 4 个元素,也可以理解为nums.Skip(1).Take(4)
范围中允许使用尾部索引
例:
nums[1..^1]:取数组索引从 1 开始的元素到最后的前 1 个元素nums[^5..^2]:取数组从倒数第 5 个元素(包含)到倒数第 2 个元素(不包含)
范围中允许省略索引
nums[x..y] 允许省略 x 和/或 y,例:
nums[1..]:取数组索引从 1 开始的元素到最后nums[..5]:取数组前 5 个元素nums[^5..]:取数组从倒数第 5 个元素到最后nums[..]:取数组所有元素
官方示例
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
类型支持
支持索引(Index)的类型
-
必须有
Length或Count属性(返回int) -
必须有 索引器
this[int]
支持范围(Range)的类型
-
必须有
Length或Count属性(返回int) -
必须有
Slice(int start, int length)方法
标准类型支持
数组、String、Span<T> 等同时支持索引和范围。
List<T> 支持索引,但不支持范围。
自定义类型支持
var myString = new MyString("Hello");
Console.WriteLine(myString[^1]); // o
Console.WriteLine(myString[1..4]); // ell
class MyString(string s)
{
// Length 或 Count
public int Length => s.Length;
// 支持索引
public char this[int index] => s[index];
// 支持范围
public MyString Slice(int start, int length)
=> new MyString(s.Substring(start, length));
public override string ToString() => s;
}
说明
- 从数组中获取范围时,结果是原数组的副本。修改新数组时,不会更改原数组的值。
- 使用范围运算符的性能取决于序列类型。例如如果序列是数组或
string,结果是原始部分的副本,时间复杂度为O(N);如果序列是System.Span<T>,结果仍然为指针引用,没有副本,时间复杂度为O(1)。

浙公网安备 33010602011771号