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)];转换为高效的等价代码,大致逻辑如下:
- 先获取
Enumerable.Range(0, 300)返回的可枚举序列; - 创建
List<int>实例,若能提前确定元素数量(比如Range的长度是明确的300),编译器会优化为预先分配对应容量的实例,避免后续扩容开销; - 将序列中的所有元素添加到新创建的
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
相关产品推荐
相关产品推荐

