You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C#中List.Sort((x,y)=>x-y)无内存分配?

为什么List.Sort(Comparison)看似创建新对象却无内存分配?

以下是List<T>.Sort(Comparison<T>)的核心实现代码:

public void Sort(Comparison<T> comparison) {
    if( comparison == null) {
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
    }
    Contract.EndContractBlock();

    if( _size > 0) {
        IComparer<T> comparer = new Array.FunctorComparer<T>(comparison);
        Array.Sort(_items, 0, _size, comparer);
    }
}

从代码看,每次调用Sort时都会创建一个Array.FunctorComparer<T>对象,但运行下面的测试代码后,却发现没有内存分配:

public static void Main(string[] args)
{
    List<int> list = new List<int>();
    list.Add(1);
    list.Add(2);
    for (int i = 0; i < 10; ++i)
    {
        long cnt = GC.GetTotalMemory(false);
        list.Sort((x ,y) => x - y);
        Console.WriteLine(GC.GetTotalMemory(false) - cnt);
    }
}

核心原因解析

  • Array.FunctorComparer<T>是值类型
    你看到的new关键字容易产生误导——实际上Array.FunctorComparer<T>是一个struct(值类型),而非引用类型。值类型的实例分配在栈上,不会占用托管堆内存,自然不会被GC.GetTotalMemory统计到。

  • JIT编译器的内联优化
    JIT会对这段代码执行激进优化:它会直接将FunctorComparer的比较逻辑内联到Sort方法中,甚至完全消除这个临时结构体的创建,直接使用传入的Comparison<T>委托完成比较操作,彻底避免了额外的内存开销。

  • 无捕获lambda的委托缓存
    测试代码中的(x,y) => x - y没有捕获外部变量,JIT会将它编译为静态方法,并缓存对应的委托实例。因此多次调用Sort时,不会每次都创建新的委托对象,进一步减少了潜在的内存分配。

内容的提问来源于stack exchange,提问作者M SLICENT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:05:35