You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中集合表达式实例化List<T>的语法及底层原理疑问

关于C#集合表达式[.. Enumerable.Range(...)]的语法解析

核心说明

你看到的不是C#8.0的范围运算符,而是C#9.0引入的集合表达式中的展开运算符,专门用于简化集合的创建与元素填充。

你的疑问解答

  • 疑问1:这种用法是否隐式执行了new List操作?
    是的。当你将集合表达式赋值给List<T>类型变量时,编译器会自动生成创建List<T>实例并填充元素的代码,完全等价于手动new List<T>()后调用AddRange的逻辑。

  • 疑问2:如何将enumerable range作为..的右侧操作数?
    这里的..不是范围运算符,而是展开运算符——它的作用是把任意实现IEnumerable<T>的对象(比如Enumerable.Range返回的序列)中的所有元素,直接“展开”到新创建的集合里。这里的左侧空白不是范围的默认起始索引,而是展开运算符的合法写法:单独使用.. 可枚举对象就能把整个序列的元素导入新集合。

底层实现逻辑

编译器会把List<int> x = [.. Enumerable.Range(0, 300)];转换为高效的等价代码,大致逻辑如下:

  1. 先获取Enumerable.Range(0, 300)返回的可枚举序列;
  2. 创建List<int>实例,若能提前确定元素数量(比如Range的长度是明确的300),编译器会优化为预先分配对应容量的实例,避免后续扩容开销;
  3. 将序列中的所有元素添加到新创建的List<int>中。

等价的手动代码类似:

var range = Enumerable.Range(0, 300);
List<int> x = new List<int>(300); // 预先分配容量,优化性能
x.AddRange(range);

如果无法提前确定元素数量,编译器会生成new List<int>(enumerable)的代码,内部同样会高效完成元素拷贝。

和C#8.0范围运算符的区别

别混淆两个..的作用:

  • C#8.0的范围运算符:用于从序列(如数组、列表)中截取子范围,比如myList[2..5]表示获取索引2到4的元素;
  • C#9.0集合表达式中的展开运算符:用于将已有可枚举对象的元素导入新集合,是集合初始化的语法糖。

内容的提问来源于stack exchange,提问作者pks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 12:47:35