enumerable.range(1, 10) 表示从1开始取10个连续整数,即1至10;其第二个参数是数量而非终点,公式为起始值+数量−1得终点,负数或溢出会抛异常,返回ienumerable需注意不可索引。

Enumerable.Range 不是用来“生成范围”的,而是“从起点开始取 N 个连续整数”——第二个参数是数量,不是终点。
Enumerable.Range(1, 10) 真实含义是什么
它生成的是 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,共 10 个数。关键不是“1 到 10”,而是“从 1 开始,要 10 个”。公式是:起始值 start,结束值(含)为 start + count - 1。
- 想生成 5 到 15(含)?别写
Enumerable.Range(5, 15)—— 那是 5~19;正确写法是Enumerable.Range(5, 11)(15 − 5 + 1 = 11 个) -
count为 0 是合法的,返回空序列;负数会直接抛ArgumentOutOfRangeException - 如果
start + count - 1 > int.MaxValue,也会抛异常,不是静默截断
为什么不用 for 循环而用 Enumerable.Range
当你只需要一个只读、不可变、延迟执行的整数序列(比如做索引遍历、填充占位、构造测试数据),且起始值和数量已知时,Enumerable.Range 更安全简洁。
- for 循环容易写错边界:比如
for (int i = 1; i 和 <code>for (int i = 1; i 差一个数,而 <code>Range(1, 10)含义唯一 -
Enumerable.Range不分配数组,不占用额外内存,遍历时才逐个产出 - 它天然支持链式组合:
Enumerable.Range(0, 100).Where(i => i % 2 == 0).Select(i => i * i),无需中间集合
常见误用与替代方案
它不支持步长、倒序、非整数、随机跳转——这些不是它的设计目标。强行硬套反而增加理解成本。
- 需要步长为 2 的偶数序列(0~10)?用
Enumerable.Range(0, 6).Select(i => i * 2),而不是试图魔改Range - 需要倒序(10~1)?优先用
Enumerable.Range(1, 10).Reverse(),别用OrderByDescending(性能差) - 需要随机整数序列?别碰
Range,改用Random类或Random.Shared - 需要字符串索引遍历?配合
Where很自然:Enumerable.Range(0, s.Length).Where(i => char.IsDigit(s[i]))
返回值不能直接索引,这点必须记住
Enumerable.Range 返回的是 IEnumerable<int></int>,不是数组或列表。你不能写 range[5],也不能反复 foreach 多次(除非源没被消费完且是可重用的,但 Range 本身是单次遍历语义)。
- 真要随机访问(比如频繁按索引取值)?加
.ToArray()或.ToList(),但代价是立即执行 + 内存分配 - 只是遍历一次?保持原样,享受延迟执行优势
- 在 LINQ 查询中嵌套使用?放心传,不会提前触发计算










