📍 索引与范围速查 Indices & Ranges
C# 8 引入 · ^ 末尾索引 · .. 范围切片 · 📖 完整课程
末尾索引Index from End — ^
核心公式:^n = Length - n。这不是随意定的——是为了让范围(Ranges)的数学性质干净。
int[] arr = [10, 20, 30, 40, 50]; // Length = 5
// ^ 映射表
^0 → 5 - 0 = 5 // 等于 Length——"末尾之后"的位置
^1 → 5 - 1 = 4 // 最后一个元素(值 50)
^2 → 5 - 2 = 3 // 倒数第二个(值 40)
^5 → 5 - 5 = 0 // 第一个元素(值 10)
// 使用
var last = arr[^1]; // 50
var secondLast = arr[^2]; // 40
// Index 是独立类型
Index i1 = ^1; // 倒数第一
Index i2 = 0; // 正向索引
^0 不是最后一个元素!它是 Length——"末尾之后"。取最后一个元素用 ^1。
这和正向索引一致:正向 0 是"开头",负向 ^0 是"结尾之后"——对称。
范围Range — ..
左闭右开:[start..end)——包含 start,不包含 end。这和 Span<T>.Slice 的语义一致。
int[] arr = [0, 1, 2, 3, 4, 5]; // 索引: 0 1 2 3 4 5
// 基本用法
arr[0..3] → [0, 1, 2] // 从开头取 3 个
arr[^3..^1] → [3, 4] // 倒数第3 到 倒数第1(不含)
arr[^3..^0] → [3, 4, 5] // 最后 3 个——^0 是 Length
// 省略语法
arr[3..] → [3, 4, 5] // 省略右端 = 到末尾
arr[..3] → [0, 1, 2] // 省略左端 = 从头开始
arr[..] → [0, 1, 2, 3, 4, 5] // 两端省略 = 全取
// ^ 省略组合
arr[^3..] → [3, 4, 5] // 省略右端 = 等价于 [^3..^0]
arr[..^1] → [0, 1, 2, 3, 4] // 去掉最后一个
Range 速查表(arr = [0,1,2,3,4,5],Length=6)
| 写法 | 等价 [start..end) | 结果 | 说明 |
arr[0..3] | [0..3) | [0,1,2] | 前 3 个 |
arr[3..6] | [3..6) | [3,4,5] | 索引 3 到末尾 |
arr[^3..^0] | [3..6) | [3,4,5] | 最后 3 个 |
arr[^3..] | [3..6) | [3,4,5] | 等价于上 |
arr[..^1] | [0..5) | [0,1,2,3,4] | 去掉最后一个 |
arr[^2..^1] | [4..5) | [4] | 倒数第二个单元素 |
arr[..] | [0..6) | 全部 | 浅拷贝 |
支持的类型
任何有 Count/Length 属性 + int 索引器 + Slice(int, int) 方法的类型:
| 类型 | 示例 |
T[] | int[], string[] |
string | str[1..^1] — 去掉首尾字符,返回 string |
Span<T> / ReadOnlySpan<T> | "Hello".AsSpan()[0..5] |
Memory<T> / ReadOnlyMemory<T> | 同 Span,堆上版本 |
List<T> | 需通过 CollectionsMarshal.AsSpan(list)[..] |
Using 声明Using Declaration (C# 8)
Using 语句(旧)
using (var conn = OpenConn())
using (var cmd = conn.CreateCmd())
{
// conn 和 cmd 在 } 时释放
}
Using 声明(新)
using var conn = OpenConn();
using var cmd = conn.CreateCmd();
// 离开作用域时释放(通常方法结束)
| Using 语句 | Using 声明 (C# 8) |
| 写法 | using (var x = ...) { } | using var x = ...; |
| 释放时机 | } 时立即释放 | 变量离开作用域时释放 |
| 有自己的作用域 | 是 | 否(变量属于父作用域) |
Using 声明在变量离开作用域时才释放(通常是方法结束)。如果资源需要尽早释放(如在重计算之前),仍需用老式 using 语句。
相关速查