范围运算符是类型系统的一部分,索引错误抛 indexoutofrangeexception;[..n] 等价 [0..n],[n..] 等价 [n..^0],均左闭右开,越界直接异常。

范围运算符不是“语法糖”而是类型系统的一部分,用错索引会直接抛 IndexOutOfRangeException,不是静默截断。
range[..n] 和 range[n..] 的边界行为差异
两者都遵循左闭右开原则,但起始点和默认终点完全不同:
-
[..n]等价于[0..n],从开头取到索引n(不含) -
[n..]等价于[n..^0],从索引n取到末尾(含n,不含^0) - 若
n超出合法范围(比如n > str.Length或n 且未用 <code>^),立刻抛异常 -
str[^0]是非法的——它对应str[str.Length],越界
用 ^ 反向索引时常见的越界陷阱
^n 表示从末尾倒数第 n 个位置,但它的底层换算是 str.Length - n,所以:
-
^1是最后一个字符(str[str.Length - 1]),合法 -
^0是字符串末尾的“空位”,str[^0]会报错,str[..^0]才是全串 -
str[^5..^2]要求字符串长度 ≥ 5,否则^5换算后为负数,触发异常 - 不要在循环中硬写
^i而不校验i ≤ str.Length
Range 类型与显式构造的适用场景
当你需要复用、传递或延迟计算范围时,应直接用 Range 类型而非语法糖:
-
var r = new Range(2, 5);明确构造,可存入变量、传参、做条件判断 -
str[r]和str[2..5]效果一致,但前者支持 null 检查、日志记录、范围验证等逻辑 - 数组/集合的
Span<t></t>或Memory<t></t>切片也依赖Range,不是所有类型都支持..语法糖 - 自定义类型要支持范围切片,必须实现
GetSlice(Index, Index)或GetSlice(int, int)成员
性能与兼容性注意事项
范围切片本身不复制底层数据(对 string、Span<t></t>、ReadOnlySpan<t></t>),但要注意:
-
string切片返回的是新字符串引用,内容仍指向原字符串的某段内存(.NET Core 2.1+ 优化),但语义上不可变 - 对
List<t></t>使用[..]会触发内部ToArray()或AsSpan(),取决于 .NET 版本和目标框架 - C# 8.0+ 才支持该语法,旧项目需确认语言版本和运行时(如 .NET Framework 4.8 不支持
^和..) - 调试时注意:VS 的“快速监视”可能不识别
^表达式,建议用str.Length - n替代临时查看
最易被忽略的一点:范围运算符的合法性检查发生在运行时,编译器几乎不介入——这意味着单元测试里漏掉边界值(比如空字符串、index=0、index=str.Length)就等于留了线上崩溃口子。










