深入理解 C# 的 Range / Index(切片语法):原理与性能解析

bandit 发布于 2026-03-30 52 次阅读


C# 8 引入了一个非常优雅的语法糖:Range / Index(切片语法)
你可能已经用过:

var sub = arr[1..^1];

但它到底是怎么工作的?
👉 是语法糖?会不会复制?性能如何?

这篇文章帮你彻底搞懂它的底层逻辑。


🧠 一、两个核心类型

C# 切片语法背后,其实是两个结构体:


🔹 Index(索引)

Index i = 3;     // 从前往后
Index j = ^1;    // 从后往前(倒数第一个)

👉 ^ 表示从末尾开始计数

等价于:

new Index(1, fromEnd: true)

🔹 Range(范围)

Range r = 1..5;

👉 表示区间 [1, 5)(左闭右开)


📦 二、语法糖展开(核心原理)

✨ 写法

var sub = arr[1..4];

🔍 编译器会做什么?

等价于(概念上):

var range = new Range(new Index(1), new Index(4));
var sub = arr.Slice(range); // 或类似逻辑

👉 关键点:

  • Range 只是描述范围
  • 真正行为由类型决定(数组 / Span / string)

⚠️ 三、数组 vs Span(本质区别)

这是最重要的部分👇


❌ 数组切片(会复制)

var sub = arr[1..4];

👉 实际行为:

var sub = new int[3];
Array.Copy(arr, 1, sub, 0, 3);

✔️ 新数组
✔️ 数据复制
❌ 有性能开销


✅ Span 切片(零拷贝)

var sub = arr.AsSpan()[1..4];

👉 实际行为:

var sub = span.Slice(1, 3);

✔️ 不创建新数组
✔️ 不复制数据
✔️ 只是改变视图范围


📊 四、图解理解(非常重要)

原数组

arr: [0][1][2][3][4][5]
        ↑

❌ arr[1..4]

new array:
[1][2][3]

👉 完整复制


✅ Span

pointer → arr[1]
length  → 3

👉 只是“看”这一段


🚀 五、常见写法总结


✔️ 基础切片

arr[0..3]   // 前3个
arr[3..]    // 从3到结尾
arr[..3]    // 从头到3
arr[..]     // 整个数组(复制)

✔️ 使用 ^(从后往前)

arr[^1]     // 最后一个
arr[^3..]   // 最后三个
arr[..^1]   // 去掉最后一个
arr[1..^1]  // 去头去尾

⚡ 六、性能分析(关键)

写法是否复制是否分配内存推荐
arr[..]
arr[1..4]
Span[..]

👉 结论:

Range 是语法糖,性能取决于底层类型!


🧠 七、为什么设计成这样?

很多人会问:

👉 为什么数组不直接支持“零拷贝切片”?

原因是:

❌ 如果数组共享内存:

  • 修改一个影响另一个
  • GC 无法正确管理
  • 容易产生隐式副作用

✅ 所以设计为:

  • 数组 → 安全(复制)
  • Span → 高性能(共享)

👉 这是一个“安全 vs 性能”的设计平衡


🔥 八、底层方法(进阶)

你可以手动使用:

arr.AsSpan().Slice(start, length);

👉 这其实就是 Range 的底层实现方式


🧠 九、一个关键认知(很多人不知道)

👉 Range 本身:

  • ❌ 不操作数据
  • ❌ 不切片
  • ✅ 只是一个“描述区间的结构体”

真正的行为由:

  • array
  • Span
  • string

来决定


🚀 十、实战建议


✔️ 普通业务代码

var sub = arr[1..4];

👉 可读性优先


✔️ 算法 / 性能优化(你现在重点)

var sub = arr.AsSpan()[1..4];

👉 零拷贝 + 高性能


✔️ 极致优化

Span<int> s = arr;
var sub = s[1..4];

📌 十一、总结

Range / Index 是语法糖,本身不做任何数据操作,真正的行为由底层类型决定。

记住这三点:

  1. .. = Range(范围)
  2. ^ = 从末尾计数
  3. 数组切片会复制,Span 不会

🧠 最终一句话

👉 Range 是“描述”,Span 才是“性能”

此作者没有提供个人介绍。
最后更新于 2026-03-30