当前位置: 首页 > news >正文

.NET/C# 的字符串暂存池

本文介绍 .NET 中的字符串暂存池。


本文内容

    • 字符串暂存池
    • 编译期间确定
    • 从暂存池中获取字符串
    • 不要池化
    • 垃圾回收

字符串暂存池

.NET 的 CLR 运行时会在运行期间管理一个字符串暂存池(string intern pool),在字符串暂存池中的字符串只有一个实例。

例如,在下面的代码中,变量 abc 都是同一个实例:

var a = "walterlv";
var b = "walterlv";
var c = "walterlv";

我有另一篇博客说到了此问题,可以参见:

  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例

字符串暂存池的出现是为了避免分配大量的字符串对象造成的过多的内存空间浪费。

编译期间确定

默认进入字符串暂存池中的字符串是那些写程序的时候直接声明或者直接写入代码中的字符串。上一节中列举的三个变量中的字符串就是直接写到代码中的字符串。

默认情况下编译期间能确定出来的字符串会写入到程序集中,运行时能直接将其放入字符串暂存池。

从暂存池中获取字符串

现在,我们要制造出编译期间不能确定出来的字符串,以便进行一些试验。

我们当然不能使用简单的 "walter" + "lv" 这样简单的字符串拼接的方式来生成字符串,因为实际上这样的字符串依然可以在编译期间完全确定。

所以这里使用 StringBuilder 来在运行期间生成字符串。

var a = "walterlv";
var b = new StringBuilder("walter").Append("lv").ToString();
var c = string.Intern(b);

Console.WriteLine(ReferenceEquals(a, b));
Console.WriteLine(ReferenceEquals(a, c));

在这段代码中,虽然 abc 三个字符串的值都是相等的,但 ab 两个字符串是不同的实例,而 ac 两个字符串是相同的实例。

我们使用了 string.Intern 方法从字符串池中取出了一个字符串的实例。

另外,string 类型还提供了 string.IsInterned 来判断一个字符串是否在字符串暂存池中。

不要池化

你可以在程序集中标记 CompilationRelaxations.NoStringInterning,这样,此程序集中的字符串就不会被池化。即便是在编译期间写下的字符串也会在运行时生成新的实例。

方法是在一个 C# 代码文件中添加特性标记。

[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]

垃圾回收

在字符串暂存池中的字符串不会被垃圾回收,你可以阅读另一篇博客:

  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉

参考资料

  • String.Intern(String) Method (System) - Microsoft Docs

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 如何为 Win32 的打开和保存对话框编写文件过滤器(Filter)
  • C# 中新增类型的命名空间只需部分与其他命名空间名称相同即可破坏源码兼容性
  • 使用 ProcessMonitor 找到进程所操作的文件的路径
  • MSBuild 在编写编译任务的时候判断当前是否在 Visual Studio 中编译
  • git 配置错误导致无法推送远端仓库?本文介绍各种修复方式
  • WPF 很少人知道的科技
  • WPF 程序的编译过程
  • 制作通过 NuGet 分发的源代码包时,如果目标项目是 WPF 则会出现一些问题(探索篇,含解决方案)
  • .NET 的程序集加载上下文
  • .NET 使用 ILMerge 合并多个程序集,避免引入额外的依赖
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • Windows 10 解决无法完整下载安装语言包(日语输入法无法下载使用)
  • 从零开始制作 NuGet 源代码包(全面支持 .NET Core / .NET Framework / WPF 项目)
  • 如何快速创建 Visual Studio 代码片段?
  • 从 git 的历史记录中彻底删除文件或文件夹
  • 【5+】跨webview多页面 触发事件(二)
  • Android框架之Volley
  • CentOS6 编译安装 redis-3.2.3
  • classpath对获取配置文件的影响
  • CSS 三角实现
  • Netty+SpringBoot+FastDFS+Html5实现聊天App(六)
  • Node 版本管理
  • React系列之 Redux 架构模式
  • Redis 懒删除(lazy free)简史
  • text-decoration与color属性
  • Webpack 4 学习01(基础配置)
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 彻底搞懂浏览器Event-loop
  • 构建二叉树进行数值数组的去重及优化
  • 构建工具 - 收藏集 - 掘金
  • 回流、重绘及其优化
  • 开源地图数据可视化库——mapnik
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 使用putty远程连接linux
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 主流的CSS水平和垂直居中技术大全
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 积累各种好的链接
  • 整理一些计算机基础知识!
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (十一)JAVA springboot ssm b2b2c多用户商城系统源码:服务网关Zuul高级篇
  • (四)鸿鹄云架构一服务注册中心
  • (一)基于IDEA的JAVA基础1
  • (转) RFS+AutoItLibrary测试web对话框
  • .cfg\.dat\.mak(持续补充)
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET CLR基本术语
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .Net Core缓存组件(MemoryCache)源码解析
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .netcore如何运行环境安装到Linux服务器
  • @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
  • [2019/05/17]解决springboot测试List接口时JSON传参异常