C#扩展数组长度有更优方案吗?当前实现代码存在什么问题?
现有代码的弊端
- 时间复杂度极高:当前实现每次仅扩容1个元素,共循环
add_size次,每次都要完整复制整个旧数组的全部元素,整体时间复杂度达到O(n²)。当add_size或原数组长度较大时,执行效率会出现指数级下降。 - 不必要的GC压力与内存浪费:每次循环都会生成一个新的临时数组,旧数组直接变为无引用的垃圾对象,扩容N次就会产生N个待回收的垃圾数组,频繁触发GC,大数组场景下还会直接进入大对象堆(LOH),引发更严重的性能问题。
- 泛用性差:当前实现仅支持
int类型数组,无法适配其他类型的数组扩容需求。 - 缺少参数校验:未对输入的
input空引用、add_size为负数等异常场景做校验,容易触发隐性bug。
更优的数组扩容实现方式
1. 优先使用.NET官方内置方法
.NET 类库已经提供了成熟的数组扩容方法Array.Resize<T>(),底层由CLR内部优化的内存复制逻辑实现,性能远高于手动写的循环复制代码,示例如下:
int[] ovride = new int[3] { 1, 2, 3 }; // Array.Resize为ref参数,会直接修改原数组引用 Array.Resize(ref ovride, ovride.Length + 10); Array.Resize(ref ovride, ovride.Length + 10); Console.WriteLine(ovride.Length);
2. 手动实现优化版扩容逻辑
如果需要自己实现扩容逻辑,直接一次性申请目标长度的数组,仅做一次内存复制即可,时间复杂度降到O(n),仅产生1个临时数组:
static T[] ExpandArray<T>(T[] input, int addSize) { // 异常参数校验 if (input == null) throw new ArgumentNullException(nameof(input)); if (addSize < 0) throw new ArgumentOutOfRangeException(nameof(addSize), "扩容大小不能为负数"); if (addSize == 0) return input; // 一次性申请足够空间,仅复制一次 T[] newArray = new T[input.Length + addSize]; Array.Copy(input, newArray, input.Length); return newArray; }
3. 频繁扩容场景直接用List<T>
如果你的业务场景需要频繁调整集合长度,建议直接使用List<T>,其内部封装了动态数组的实现,默认扩容策略为每次容量翻倍,避免了频繁复制的性能损耗,无需手动处理扩容逻辑:
// 初始化时可以指定初始容量减少不必要的扩容 List<int> list = new List<int>(3) {1,2,3}; // 提前预知要新增10个元素的话可以预扩容 list.Capacity += 10; // 直接新增元素即可,内部自动处理扩容 for(int i = 0; i < 10; i++) { list.Add(i); } // 需要转数组的话调用ToArray即可 int[] arr = list.ToArray();
内容的提问来源于stack exchange,提问作者user16414459
相关产品推荐
相关产品推荐

