网易首页 > 网易号 > 正文 申请入驻

C#|.net core 基础 - 扩展数组添加删除性能最好的方法

0
分享至

今天在编码的时候遇到了一个问题,需要对数组变量添加新元素和删除元素,因为数组是固定大小的,因此对新增和删除并不友好,但有时候又会用到,因此想针对数组封装两个扩展方法:新增元素与删除元素,并能到达以下三个目标:

1、性能优异;

2、兼容性好;

3、方便使用;

这三个目标最麻烦的应该就是性能优异了,比较后面两个可以通过泛型方法,扩展方法,按引用传递等语法实现,性能优异却要在十来种实现方法中选出两个最优的实现。那关于数组新增和删除元素你能想到多少种实现呢?下面我们来一起看看哪个性能最好。

01、新增元素实现方法对比

1、 通过List方法实现

通过转为List,再用AddRange方法添加元素,最后再转为数组返回。代码实现如下:

public static int[] AddByList(int[] source, int[] added)
var list = source.ToList();
list.AddRange(added);
return list.ToArray();

2、通过IEnumerable方法实现

因为数组实现了IEnumerable接口,所以可以直接调用Concat方法实现两个数组拼接。代码实现如下:

public static int[] AddByConcat(int[] source, int[] added)
return source.Concat(added).ToArray();

3、通过Array方法实现

Array有个Copy静态方法可以实现把数组复制到目标数组中,因此我们可以先构建一个大数组,然后用Copy方法把两个数组都复制到大数组中。代码实现如下:

public static int[] AddByCopy(int[] source, int[] added)
var size = source.Length + added.Length;
var array = new int[size];
// 复制原数组
Array.Copy(source, array, source.Length);
// 添加新元素
Array.Copy(added, 0, array, source.Length, added.Length);
return array;

4、通过Span方法实现

Span也有一个类似Array的Copy方法,功能也类似,就是CopyTo方法。代码实现如下:

public static int[] AddBySpan(int[] source, int[] added)
Span sourceSpan = source;
Span addedSpan = added;
Span span = new int[source.Length + added.Length];
// 复制原数组
sourceSpan.CopyTo(span);
// 添加新元素
addedSpan.CopyTo(span.Slice(sourceSpan.Length));
return span.ToArray();

我想到了4种方法来实现,如果你有不同的方法希望可以给我留言,不吝赐教。那么哪种方法效率最高呢?按我理解作为现在.net core性能中的一等公民Span应该性能是最好的。

我们也不瞎猜了,直接来一组基准测试对比。我们对4个方法,分三组测试,每组分别随机生成两个100、1000、10000个元素的数组,然后每组再进行10000次测试。

测试结果如下:

整体排名:AddByCopy > AddByConcat > AddBySpan > AddByList。

可以发现性能最好的竟然是Array的Copy方法,不但速度最优,而且内存使用方面也是最优的。

而我认为性能最好的Span整体表现还不如IEnumerable的Concat方法。

最终Array的Copy方法完胜。

02、删除元素实现方法对比

1、通过List方法实现

还是先把数组转为List,然后再用RemoveAll进行删除,最后把结果转为数组返回。代码实现如下:

public static int[] RemoveByList(int[] source, int[] added)
var list = source.ToList();
list.RemoveAll(x => added.Contains(x));
return list.ToArray();

2、通过IEnumerable方法实现

因为数组实现了IEnumerable接口,所以可以直接调用Where方法进行过滤。代码实现如下:

public static int[] RemoveByWhere(int[] source, int[] added)
return source.Where(x => !added.Contains(x)).ToArray();

3、通过Array方法实现

Array有个FindAll静态方法可以实现根据条件查找数组。代码实现如下:

public static int[] RemoveByArray(int[] source, int[] added)
return Array.FindAll(source, x => !added.Contains(x));

4、通过For+List方式实现

直接遍历原数组,把满足条件的元素放入List中,然后转为数组返回。代码实现如下:

public static int[] RemoveByForList(int[] source, int[] added)
var list = new List();
foreach (int item in source)
if (!added.Contains(item))
list.Add(item);

return list.ToArray();

5、通过For+标记+Copy方式实现

还是直接遍历原数组,但是我们不创建新集合,直接把满足的元素放在原数组中,因为从原数组第一个元素迭代,如果元素满足则放入第一个元素其索引自动加1,如果不满足则等下一个满足的元素放入其索引保持不变,以此类推,直至所有元素处理完成,最后再把原数组中满足要求的数组复制到新数据中返回。代码实现如下:

public static int[] RemoveByForMarkCopy(int[] source, int[] added)
var idx = 0;
foreach (var item in source)
if (!added.Contains(item))
// 标记有效元素
source[idx++] = item;

// 创建新数组并复制有效元素
var array = new int[idx];
Array.Copy(source, array, idx);
return array;

6、通过For+标记+Resize方式实现

这个方法和上一个方法实现基本一致,主要差别在最后一步,这个方法是直接通过Array的Resize静态方法把原数组调整为我们要的并返回。代码实现如下:

public static int[] RemoveByForMarkResize(int[] source, int[] added)
var idx = 0;
foreach (var item in source)
if (!added.Contains(item))
//标记有效元素
source[idx++] = item;

//调整数组大小
Array.Resize(ref source, idx);
return source;

同样的我们再做一组基准测试对比,结果如下:

可以发现最后两个方法随着数组元素增加性能越来越差,而其他四种方法相差不大。既然如此我们就选择Array原生方法FindAll。

03、实现封装方法

新增删除的两个方法已经确定,我们第一个目标就解决了。

既然要封装为公共的方法,那么就必要要有良好的兼容性,我们示例虽然都是用的int类型数组,但是实际使用中不知道会碰到什么类型,因此最好方式是选择泛型方法。这样第二个目标就解决了。

那么第三个目标方便使用要怎么办呢?第一想法既然做成公共方法了,直接做一个帮助类,比如ArrayHelper,然后把两个实现方法直接以静态方法放进去。

但是我更偏向使用扩展方法,原因有二,其一可以利用编辑器直接智能提示出该方法,其二代码更简洁。形如下面两种形式,你更喜欢哪种?

//扩展方法
var result = source.Add(added);
//静态帮助类方法
var result = ArrayHelper.Add(source, added);

现在还有一个问题,这个方法是以返回值的方式返回最后的结果呢?还是直接修改原数组呢?两种方式各有优点,返回新数组,则原数组不变便于链式调用也避免一些副作用,直接修改原数组内存效率高。

我们的两个方法是新增元素和删除元素,其语义更贴合对原始数据进行操作其结果也作用在自身。因此我更倾向无返回值的方式。

那现在有个尴尬的问题,不知道你还记得我们上一章节《C#|.net core 基础 - 值传递 vs 引用传递》讲的值传递和引用传递,这里就有个这样的问题,如果我们现在想用扩展方法并且无返回值直接修改原数组,那么需要对扩展方法第一个参数使用ref修饰符,但是扩展方法对此有限制要求【第一个参数必须是struct 或是被约束为结构的泛型类型】,显示泛型数组不满足这个限制。因此无法做到我心目中最理想的封装方式了,下面看看扩展方法和帮助类的代码实现,可以按需使用吧。

public static class ArrayExtensions
public static T[] AddRange(this T[] source, T[] added)
var size = source.Length + added.Length;
var array = new T[size];
Array.Copy(source, array, source.Length);
Array.Copy(added, 0, array, source.Length, added.Length);
return array;
public static T[] RemoveAll(this T[] source, Predicate match)
return Array.FindAll(source, a => !match(a));

public static class ArrayHelper
public static void AddRange(ref T[] source, T[] added)
var size = source.Length + added.Length;
var array = new T[size];
Array.Copy(source, array, source.Length);
Array.Copy(added, 0, array, source.Length, added.Length);
source = array;
public static void RemoveAll(ref T[] source, Predicate match)
source = Array.FindAll(source, a => !match(a));

:测试方法代码以及示例源码都已经上传至代码库,有兴趣的可以看看。https://gitee.com/hugogoos/Planner

声明:个人原创,仅供参考

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
郑大一附院​暴雷!无医德无医风胆大妄为,说是蛇鼠一窝都不为过

郑大一附院​暴雷!无医德无医风胆大妄为,说是蛇鼠一窝都不为过

达文西看世界
2026-02-05 19:50:46
别想歪!这幅人体油画靠“光”就能让你呼吸放缓?答案藏在薄纱里

别想歪!这幅人体油画靠“光”就能让你呼吸放缓?答案藏在薄纱里

陈洪标写字说画
2026-01-27 22:31:02
这仨生肖春节财运爆棚!不是运气好,是心态对了!

这仨生肖春节财运爆棚!不是运气好,是心态对了!

毅谈生肖
2026-02-06 12:48:18
人不会无缘无故患带状疱疹!调查发现:得带状疱疹,离不开这4点

人不会无缘无故患带状疱疹!调查发现:得带状疱疹,离不开这4点

蜉蝣说
2026-02-04 14:40:05
艾滋病新增130万!很多人中招很冤枉!在外“5不碰”一定要记死

艾滋病新增130万!很多人中招很冤枉!在外“5不碰”一定要记死

今朝牛马
2025-12-31 19:31:04
某鱼惊现“天价笔”:800元一支的中性笔,藏着多少肮脏暗语?

某鱼惊现“天价笔”:800元一支的中性笔,藏着多少肮脏暗语?

戗词夺理
2026-01-24 16:05:41
强势打脸C罗!沙特联赛官方:他无权干涉其他球队 应专注自身表现

强势打脸C罗!沙特联赛官方:他无权干涉其他球队 应专注自身表现

风过乡
2026-02-06 05:47:50
现货白银收跌20.06%,报70.902美元/盎司

现货白银收跌20.06%,报70.902美元/盎司

每日经济新闻
2026-02-06 06:26:13
“流氓有文化更可怕”,退休老干部频繁联系女幼师,聊天记录曝光

“流氓有文化更可怕”,退休老干部频繁联系女幼师,聊天记录曝光

妍妍教育日记
2026-01-27 19:58:28
同居变群居!男子与女友同居后被女友5个闺蜜缠上,拿捏得死死的

同居变群居!男子与女友同居后被女友5个闺蜜缠上,拿捏得死死的

今朝牛马
2026-01-16 17:30:01
牛鬼神蛇现原形!聂卫平去世仅一天,私生活被扒,王刚郎平被牵连

牛鬼神蛇现原形!聂卫平去世仅一天,私生活被扒,王刚郎平被牵连

春露秋霜
2026-01-16 06:27:20
安理会以“最强烈措辞”谴责

安理会以“最强烈措辞”谴责

陆弃
2026-02-05 10:12:22
爱泼斯坦前女友在牢房活动监控曝光:四周都是白墙,身着橙色囚服躺床上看书

爱泼斯坦前女友在牢房活动监控曝光:四周都是白墙,身着橙色囚服躺床上看书

潇湘晨报
2026-02-06 11:26:12
复出延期!崔永熙将缺席CBA杯赛 第二阶段再复出驰援广东

复出延期!崔永熙将缺席CBA杯赛 第二阶段再复出驰援广东

醉卧浮生
2026-02-06 12:08:31
乌克兰大规模空袭圣彼得堡等地,击中俄运兵列车、炼油厂多个目标

乌克兰大规模空袭圣彼得堡等地,击中俄运兵列车、炼油厂多个目标

火星宏观
2026-02-06 11:45:31
德国总理:欧洲要知耻,除了中文和英语,世界上应该有第三种声音

德国总理:欧洲要知耻,除了中文和英语,世界上应该有第三种声音

议纪史
2026-02-05 14:40:03
叛国者黄宇细节曝光:十年间出卖15万余份资料,原单位29人受处分

叛国者黄宇细节曝光:十年间出卖15万余份资料,原单位29人受处分

谈史论天地
2026-02-06 13:30:03
大爆冷!2换1特雷杨+9换4浓眉哥连续补强后 倒数第二力擒东部第一

大爆冷!2换1特雷杨+9换4浓眉哥连续补强后 倒数第二力擒东部第一

锅子篮球
2026-02-06 12:29:37
专家提醒:不要买!不要吃!里面含有硼砂,危害健康,别害了自己

专家提醒:不要买!不要吃!里面含有硼砂,危害健康,别害了自己

蜉蝣说
2025-10-31 10:56:39
中方火力全开,巴拿马踢到铁板,特朗普来电交底,不想跟中国翻脸

中方火力全开,巴拿马踢到铁板,特朗普来电交底,不想跟中国翻脸

东极妙严
2026-02-05 15:28:10
2026-02-06 14:32:49
IT规划师
IT规划师
热爱编程,追求最佳实践,喜欢思想的碰撞
78文章数 906关注度
往期回顾 全部

科技要闻

微信封禁元宝红包后,又把阿里千问封了

头条要闻

女子付4980元买500双鞋仅收90余双 涉事商家销号失联

头条要闻

女子付4980元买500双鞋仅收90余双 涉事商家销号失联

体育要闻

西甲射手榜第2,身价不到姆巴佩1/40

娱乐要闻

微博之夜红毯好精彩,堪比婚礼现场

财经要闻

很意外,美债危机要化解了

汽车要闻

标配华为乾崑解决方案 华境S完成六座满载冬测

态度原创

艺术
本地
游戏
教育
房产

艺术要闻

Kristin Vestgard:挪威当代画家

本地新闻

围观了北京第一届黑色羽绒服大赛,我笑疯了

快上车!腾讯新作《粒粒的小人国》首测即将开启,手慢无!

教育要闻

换成你如何回答孩子?是像梅宇一样继续误导孩子,还是有别的方式!

房产要闻

新春三亚置业,看过这个热盘再说!

无障碍浏览 进入关怀版