string知多少
C#中string关键字相信大家都不陌生,很熟悉。今天主要讲的内容呢,就是围绕着这个简单的关键字。
string在C#中是用来定义字符串变量的关键字,很普通,普通得大家可以忽视她,如果你忽视了她,那么你已经失去了一段美好的回忆。下面我们就来追溯这段回忆吧。
首先介绍两个概念:1、字符串池,2、字符串驻留池
1、 字符串池是编译器为执行过程中程序映像和内存中的相同字符串创建单个副本,从而得到较小的程序。
2、 字符串驻留池是CLR初始化时创建一个内部哈希表,表的key是字符串,value是托管堆中String的引用,该表就是驻留池。因为字符串是不变量,如果内存中存在多个相同字符串的实例,便会造成内存的浪费,故高级语言(C#、Java)等都用了字符串驻留池来提高内存利用率。
在这里首先介绍这两个概念的用意是为了告诉大家字符串池和字符串驻留池是不同的概念,不可混淆。
字符串在.Net世界里是如何存储的呢?
我们先看如下流程图:
1、
说明:我们以上操作创建了一个”AaronPan”不变量字符串,然后经C#编译器字符串池机制优化了程序集(这里也可以设置编译器关闭字符串池机制[C++编译器默认关闭字符串池],我们针对一般情况,特殊情况忽略),当程序集加载到应用程序域时,CLR2.0版本以上默认会驻留程序集中不变量字符串。
2、
说明:eng_Name并没有创建新的字符串,eng_Name和name引用了托管堆中同一个不变量字符串。
3、
说明:name,eng_Name,full_Name引用了0x~位置的字符串实例,而my_Name则引用了0x$位置的字符串实例。因为full_Name由两个不变量字符串串联起来的,编译器直接认为是”AaronPan”,而my_Name由两个变量串联起来,我们查看IL可以发现两个变量通过Concat()创建了一个新的字符串。
4、
说明:这里采用String类Intern方法访问字符串驻留池。因为驻留池中已经存在一个完全相同的字符串,所以返回匹配字符串的引用,而0x$位置的实例则等待GC回收。
注:
1、 字符串驻留池引用的字符串不会被垃圾回收器回收,其生命周期会伴随着应用程序进程终止而终止。
2、 字符串驻留池虽然可以提高内存利用率,但他要额外维护一个内部哈希表,性能必定会下降,我们可以在C#编译器设置不开启字符串驻留功能(CompilationRelaxations.NoStringInterning都被编译器忽略了,不知道是不是JIT搞的鬼)。根据实际场景,合理应用。
——Aaron.Pan
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验