数组需为泛型类型(如int[]、string[])且引用System.Linq命名空间才能调用ToList(),它创建新List并复制元素,不与原数组共享数据。

数组直接调用 ToList() 就行,但得是泛型数组
不是所有数组都能直接用 ToList() —— 只有实现了 IEnumerable 的泛型数组(比如 int[]、string[])才支持。非泛型数组(如 Array 类型或老式 object[] 且元素类型不一致)会编译报错或运行时出问题。
常见错误现象:CS1061 “Array” does not contain a definition for “ToList”,说明你拿的是裸 Array 实例,不是 T[]。
- 正确写法:
int[] arr = { 1, 2, 3 }; var list = arr.ToList(); - 错误写法:
Array arr = new int[] { 1, 2, 3 }; var list = arr.ToList(); // 编译不过 - 如果只有
object[]且确定全是string,先 cast 再调用:((string[])objArr).ToList()
ToList() 是 LINQ 方法,必须引用 System.Linq
没加 using System.Linq; 会导致编译器完全不认识 ToList(),哪怕数组类型完全正确也会报错。
使用场景很常见:从数据库查出数组、配置读取为数组、旧代码返回 T[] 但后续逻辑需要 List 的增删能力。
- 忘记引用时的错误信息:
CS1061 “int[]” does not contain a definition for “ToList” - 不光是
ToList(),所有 LINQ 扩展方法(Where、Select等)都依赖这个命名空间 - .NET Core / .NET 5+ 项目默认包含
System.Linq,但某些精简模板(如 Unity C# 或旧 .NET Framework 控制台项目)可能没自动引入
性能上没额外开销,但要注意“新对象”语义
ToList() 每次都创建一个新 List 实例,内部复制数组内容。它不是包装器,也不共享底层存储。
这意味着:修改原数组不影响新 List,修改 List 也不影响原数组 —— 这是安全的,但也意味着如果你误以为它们“绑定”,就容易出逻辑 bug。
- 性能影响:O(n) 时间 + O(n) 内存,和手动
new List几乎一样快(arr) - 别这么写:
var list = arr.ToList(); arr[0] = 999; // list[0] 还是原来的值 - 如果真想共享数据或避免复制,考虑用
Array.AsReadOnly()或直接传IEnumerable,而不是硬转List
替代方案:不用 LINQ 也能转,但更啰嗦
如果因为某种原因不能用 LINQ(比如受限于目标框架或代码规范),可以用构造函数直接初始化:
-
var list = new List—— 最接近(arr); ToList()行为,也要求arr是int[] -
var list = new List—— 多一次方法调用,略慢一点(); list.AddRange(arr); -
var list = arr.Select(x => x).ToList();—— 完全没必要,纯属画蛇添足
真正容易被忽略的是:ToList() 返回的 List 是可变集合,而原始数组是固定长度的。一旦开始往 List 里 Add/Remove,就彻底和数组无关了——这点在多线程或缓存场景下尤其关键。











