在 .NET 中的 ConvertAll 和 Select 方法哪个性能好

.NET 的 List 中提供了 ConvertAllSelect 两个方法,在开发中实际上应该使用哪一个?

接下来通过基准测试脚本来对比性能。

先编写基准测试脚本:

csharp 复制代码
[MemoryDiagnoser]  
public class BenchmarksTerrible  
{  
    private readonly List<Order> _orders;  
  
    public BenchmarksTerrible()  
    {  
        var random = new Random(420);  
        _orders = Enumerable.Range(1, 100000).Select(_ => new Order { Status = random.Next().ToString() })  
            .ToList();;  
    }  
  
    public static OrderBasicInfo ConvertOrder(Order order) => new() { Status = order.Status };  
      
    public List<OrderBasicInfo> GetOrderBasicInfos() => _orders.ConvertAll(new Converter<Order, OrderBasicInfo>(ConvertOrder));
    
  
  
    [Benchmark]  
    public List<OrderBasicInfo> ConvertAll()  
    {  
        return GetOrderBasicInfos();  
    }  
  
    [Benchmark]  
    public void Select()  
    {  
        var _ = _orders.Select(x => new OrderBasicInfo { Status = x.Status });  
    }  
  
    [Benchmark]  
    public List<OrderBasicInfo> SelectToList()  
    {  
        return _orders.Select(x => new OrderBasicInfo { Status = x.Status })  
            .ToList();  
    }  
}

测试结果如下:

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ConvertAll 4,118,657.86 ns 77,004.920 ns 79,078.383 ns 382.8125 375.0000 132.8125 3200166 B
Select 14.70 ns 0.287 ns 0.330 ns 0.0076 - - 72 B
SelectToList 4,115,770.49 ns 68,067.640 ns 63,670.513 ns 382.8125 375.0000 132.8125 3200174 B

然后将代码的 GetOrderBasicInfos 方法进行如下调整,重新测试。

csharp 复制代码
public List<OrderBasicInfo> GetOrderBasicInfos() => _orders.ConvertAll(ConvertOrder);  

测试结果如下:

Method Mean Error StdDev Gen0 Gen1 Gen2 Allocated
ConvertAll 4,160,022.71 ns 57,100.202 ns 50,617.842 ns 382.8125 375.0000 132.8125 3200166 B
Select 14.49 ns 0.209 ns 0.174 ns 0.0076 - - 72 B
SelectToList 4,118,527.16 ns 58,763.369 ns 49,070.075 ns 382.8125 375.0000 132.8125 3200174 B

经过两次测试可以发现,Select 方法的性能最好,因为它的执行时间最短,分配的内存最少,并且几乎不需要垃圾回收。ConvertAllSelectToList 方法的执行时间非常接近,SelectToList 稍好一些,但都比 Select 方法慢得多,且分配的内存较多,垃圾回收次数也较高。

因此,对于开头的问题,我的结论是两个方法的性能差不多,都可以使用。

相关推荐
刚子编程8 小时前
用 Inno Setup 把 .NET 程序打包成安装包:从零到发布的完整指南
.net·inno setup·码农刚子·.net 程序打包·安装脚本编写
界面开发小八哥10 小时前
界面控件DevExpress Blazor v26.1新版亮点 - TreeList & 数据编辑器
javascript·编辑器·.net·界面控件·blazor·devexpress·用户界面
rockey62721 小时前
C#脚本引擎之AScript与Flee对比
c#·.net·script·eval·动态脚本
海盗12341 天前
微软技术周报 · 2026-08-11~2026-08-18
人工智能·microsoft·.net
Leinwin1 天前
微软MAI-Code-1.1-Flash技术解读:Token效率提升25%,CLI与.NET全面升级
microsoft·.net
慧都小妮子2 天前
C# 实现AI合同审查:从读取、风险标注到批量签发
ai·自然语言处理·c#·.net·办公自动化·ai合同审查·文档ai代理
唐青枫5 天前
别把 ImmutableArray 当成只读 List:C#.NET 不可变数组深入详解
c#·.net
微小冷6 天前
海康威视相机C#二次开发环境配置
数码相机·c#·.net·海康威视·相机开发
唐青枫6 天前
别只会解析参数:C#.NET Spectre.Console.Cli 命令行工具实战详解
c#·.net
rockey6277 天前
基于AScript的Lua脚本语言发布啦
c#·.net·lua·script·动态脚本