为何已Intern的C#字符串列表仍占用8MB高内存?
问题解答
是的,这完全是C# List<string>的固有工作机制,原因如下:
List
的底层存储本质 List<T>是托管数组的包装类,对于引用类型(比如string),数组中存储的是每个元素的引用指针,而非字符串实例本身。即使所有字符串都指向同一个Interned的实例,List仍需要为每个元素存储这个实例的地址。内存占用的计算
在64位.NET进程中,每个引用指针的大小是8字节。100万条引用的总内存就是:1,000,000 × 8字节 = 8,000,000字节 ≈ 8MB
这正好和你在dotMemory中看到的内存占用一致。如果是32位进程,每个引用是4字节,内存占用会是4MB。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
相关产品推荐
相关产品推荐

