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

为何已Intern的C#字符串列表仍占用8MB高内存?

问题解答

是的,这完全是C# List<string>的固有工作机制,原因如下:

  1. List的底层存储本质
    List<T>是托管数组的包装类,对于引用类型(比如string),数组中存储的是每个元素的引用指针,而非字符串实例本身。即使所有字符串都指向同一个Interned的实例,List仍需要为每个元素存储这个实例的地址。

  2. 内存占用的计算
    在64位.NET进程中,每个引用指针的大小是8字节。100万条引用的总内存就是:
    1,000,000 × 8字节 = 8,000,000字节 ≈ 8MB
    这正好和你在dotMemory中看到的内存占用一致。如果是32位进程,每个引用是4字节,内存占用会是4MB。

  3. string.Intern的作用边界
    string.Intern的作用是让相同内容的字符串共享同一个实例,从而节省字符串本身的内存开销,但它不会改变List存储引用的本质——List仍然需要为每个位置保存指向共享实例的指针,这部分内存是List结构本身的必要开销,无法通过Intern消除。

你的代码示例

int maxCount = 1_000_000;

var list1 = new List<string>(maxCount);

string val = "input1.country == \"india\" AND input1.loyaltyFactor <= 2 AND input1.totalPurchasesToDate >= 5000 AND input2.totalOrders > 2 AND input3.noOfVisitsPerMonth > 2";
for (var ix = 0; ix < maxCount; ix++)
{
    list1.Add(string.Intern(val));
}
var totalMemory = GC.GetTotalMemory(false);
Console.WriteLine(totalMemory/1024 + "KB");

Console.ReadKey();
Console.Write(list1[0]);

补充说明

你初始化List时指定了maxCount,这让List直接分配了能容纳100万元素的数组,避免了动态扩容带来的额外内存开销,所以内存占用刚好等于所有引用指针的总大小。如果没有指定初始容量,List会多次扩容,内存占用会略高于8MB。

内容的提问来源于stack exchange,提问作者Lydon Ch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 02:45:04