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

调用ToUpper()等方法后,旧字符串对象是否会被GC回收?

关于C#字符串与GC的两个问题解答

嘿,咱们把这两个问题拆开来聊清楚——结合你已经了解GC不可预测性的前提,咱们直接说核心逻辑:

问题1:调用ToUpper()等方法后,旧的string对象是否会被垃圾回收(GC)?

首先得敲黑板记住:C#里的string是不可变类型——所有像ToUpper()、ToLower()、Replace()这类看似“修改”字符串的方法,本质上都不会改动原字符串对象,而是返回一个全新的字符串对象(除非原字符串已经满足方法的结果要求,比如原字符串本来就是全大写,这时候ToUpper()会直接返回原对象的引用,这种情况旧对象当然不会被GC盯上)。

那回到问题本身:调用ToUpper()后旧对象会不会被GC回收,核心看有没有其他引用还指向它:

  • 如果旧对象没有任何其他引用(比如只有原来的变量指向它,现在变量已经切换到新对象了),那它就会被标记为可回收对象,等待GC在合适的时机处理(毕竟你也知道GC的执行时机是不可预测的)。
  • 如果还有其他地方在引用这个旧对象(比如另一个变量也指向它,或者它是字符串字面量被CLR驻留了),那GC就不会碰它。

问题2:执行代码string str = "Hello World!"; str = str.ToUpper();后,旧字符串对象会被GC回收,还是仍指向同一对象?

先拆解这段代码的执行逻辑:

  1. 第一行string str = "Hello World!";:这里的"Hello World!"是字符串字面量,CLR会把它加入到「字符串驻留池」中——这个池子会保留这些字面量的引用,避免重复创建相同的字符串对象,节省内存。
  2. 第二行str = str.ToUpper();:因为原字符串是混合大小写,ToUpper()会生成一个全新的"HELLO WORLD!"字符串对象(这个新字面量也会被驻留),然后str变量的引用从旧对象切换到新对象。

那旧的"Hello World!"对象会不会被GC回收?答案是不会——因为它在字符串驻留池里还有引用,CLR会一直保留驻留池里的字符串字面量,直到应用程序退出。

如果换个场景:比如旧字符串是动态生成的(比如string str = new string(new char[]{'H','e','l','l','o'})),没有被驻留,那当str指向新对象后,旧对象没有其他引用,就会被标记为可回收,等待GC处理。


内容的提问来源于stack exchange,提问作者Phil C

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:31:34