文档章节

C#字符串暂存池

王小力
 王小力
发布于 2016/05/09 22:01
字数 1093
阅读 34
收藏 0
点赞 2
评论 0

今天偶然看到String.Intern这个方法感觉特别好奇,查了一下msdn发现有这么一段描述

公共语言运行时维护名为暂存池,其中包含对每个声明或在程序中以编程方式创建的唯一字符串的单个引用的表,从而节约的字符串存储空间。
因此,存在一个实例并用特定值的文字字符串的仅一次在系统中

这里面提到了暂存池,关于这个有很多种叫法,在这里还是使用msdn的翻译:”暂存池“。有时候会经常讨论:”多个相同的字符串到底会不会被保存到暂存池中么“,来做几个测试就明白了

var a = "123";
var b = "123";
var c = "1" + "2" + "3";
var d = String.Empty;
for (int i = 1; i < 4; i++)
{
    d += i.ToString();
}

代码中声明了四个变量,变量的值是相同的,那么地址是否相同呢?

在immediate window中查看结果如下:

&a
0x0780ec08
    *&a: {37688668}
&b
0x0780ec04
    *&b: {37688668}
&c
0x0780ec00
    *&c: {37688668}
&d
0x0780ebfc
    *&d: {37688840}

以变量a为例 :&a表示要获取变量a的地址,下面的 0x0780ec08表示该变量在栈上的地址,对应的*&a:{37688688}表示 0x0780ec08地址中存储的值,对于引用类型而言该值也是一个地址,所以{37688688}这个地址应该是指向了字符串的存储位置。当然,这个也可以通过Object.ReferenceEquals这个方法来验证两个对象是否相等,对比结果如下:

a和b:True
a和c:True
a和d:False

所以从上述两种测试结果看发现变量a、变量b、变量c的地址是相同的,唯独变量d的地址不同。所以在这里可以先简单得出一个结论:”在进行初始化时以非编程方式声明的相同值的字符串会被保存在字符串暂存池的同一位置

其实我自己得出的这个结论和文章开头引用的msdn对暂存池的定义存在冲突的地方,接下来通过String.Intern这个神奇的方法来证明一个字符串是否是在暂存池,首先先看Intern方法的定义:

Intern 方法使用暂存池来搜索字符串的值等于 str如果存在这样的字符串,则返回它在暂存池中的引用。如果该字符串不存在,对引用 str 添加到暂存池中,则返回该引用。

测试代码:

var x = "abc";
var y = new StringBuilder().Append("a").Append("b").Append("c").ToString();
var z = string.Intern("abc");

上面代码中变量x、变量y、变量z的值是相同的,都是abc。变量z是通过String.Intern从暂存池获取字符串“abc”,所以通过这个变量z就可以看出变量x与变量y谁在暂存池

immediate window测试结果如下:

&x
0x077fec98
    *&x: {38737244}
&y
0x077fec94
    *&y: {38737440}
&z
0x077fec90
    *&z: {38737244}

Object.ReferenceEquals比较结果如下:

x==y:False
x==z:True

结果很明先,变量x是保存在暂存池中的,变量y由于是通过“编程”的方式声明的,所以不再暂存池中。当然可能有人要问,如果上面的代码把变量x声明去掉呢?变量y会不会被保存到暂存池?其实去掉也是一样的,去掉变量x的声明以后当String.Intern("abc")暂存池查找变量abc时发现这个值不存在,会将abc这个字符串值添加到暂存池并返回一个新的地址引用给变量z,所以变量z和变量y的引用地址还是不相同。

结束

从上述的测试结果可以看出,当程序在初始化的时候会将以非编程方式声明的字符串变量保存到暂存池,从而节约字符串存储空间,但是在msdn的定义中也提到以编程方式创建的字符串也会保存到暂存池,这个与上述的测试结果不符,或者是我个人理解有错误,如果哪位朋友有更好的理解或测试方法还望不吝赐教 :D

测试使用了vs2015+Framework4.6。^_^


© 著作权归作者所有

共有 人打赏支持
王小力
粉丝 0
博文 1
码字总数 1093
作品 0
海淀
程序员
1、C#语法基础知识

面向对象 封装,继承,多态 封装-把很多重复的代码封装到一个方法中,把字段封装成属性,把多个参数封装成一个对象 把很多重复功能的类封装到一个dll文件中 继承-类与类之间的关系 在C#中有个...

神补刀 ⋅ 2015/12/30 ⋅ 0

C#的字符串优化-String.Intern、IsInterned

首先看一段程序: 这个没有什么特殊的地方,相信大家都知道运行结果: 第二个WriteLine使用==比较两个字符串,返回False是因为他们不一致。而最后一个WriteLine返回False,因为a、b的引用不一...

小匠头 ⋅ 2017/11/28 ⋅ 0

【求助】C# IIS8 相关API 如何查找??

求助啊,怎么找了半天都找不到有关 IIS 8.5 的操作文档啊, MSDN 用的不熟啊,找不到 IIS 开发的API,特发布求助帖子,望大虾指教啊。 (C# 如何操作IIS 8.5,哪里能够找到相关的文档,比如获...

loongchao ⋅ 2014/11/16 ⋅ 3

Git

初始化一个仓库 将所有文件添加到git仓库(暂存区) 提交到本地仓库(分支) 查看仓库的状态 查看更改信息 查看仓库日志 查看日志 ^的个数相当于回退几个版本 表示当前所处在的版本 跳转到指...

FutaoSmile丶 ⋅ 2017/09/30 ⋅ 0

C# WinForm开发系列 - Thread/Delegate/Event

C#是一门支持多线程的语言,因此线程的使用也是比较常见的。由于线程的知识在Win32编程的时候已经说得过多,所以在.Net中很少介绍这部分(可能.Net不觉得这部分是它所特有的)。那我们为什么...

长征2号 ⋅ 2017/10/11 ⋅ 0

ADO.NET中SQL Server数据库连接池

实际上,大多数应用程序仅使用一个或几个不同的连接配置。 这意味着在执行应用程序期间,许多相同的连接将反复地打开和关闭。 为了使打开的连接成本最低,ADO.NET 使用称为连接池的优化方法。...

zting科技 ⋅ 2017/01/12 ⋅ 0

Git基础入门(一)Git基础概念

Git和传统版本控制系统的区别: 传统版本控制系统: 1、将数据保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异 2、只记录发生改变的数据 3、每次克隆只获取最新的内容 Git: 1、...

红尘世间 ⋅ 2017/10/22 ⋅ 0

线程池,千万注意,原来很多人都在错用

[C#线程池] 场景:以下是C# winform写的一个线程池示例程序。窗体上,分别拖放一个开始和停止按钮,单击开始按钮,for寻觅模拟7000个任务队列,在线程池运行过程中,可以点击停止按钮,来结束...

李朝强 ⋅ 2016/10/28 ⋅ 0

【Git入门之二】基本术语

工欲善其事必先利其器,首先请原谅我蹩脚的英文翻译。 1.分支(Braches) 一个分支意味着它是一个独立拥有自己历史版本信息的代码线。你可以从已有的代码中生成一个新的分支,这个分支与其余...

yangxiaoxiao ⋅ 2014/01/05 ⋅ 0

C#多线程学习(四) 多线程的自动管理(线程池)

本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习(五) 多线...

Yamazaki ⋅ 2012/03/29 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Sqoop

1.Sqoop: 《=》 SQL to Hadoop 背景 1)场景:数据在RDBMS中,我们如何使用Hive或者Hadoop来进行数据分析呢? 1) RDBMS ==> Hadoop(广义) 2) Hadoop ==> RDBMS 2)原来可以通过MapReduce I...

GordonNemo ⋅ 15分钟前 ⋅ 0

全量构建和增量构建的区别

1.全量构建每次更新时都需要更新整个数据集,增量构建只对需要更新的时间范围进行更新,所以计算量会较小。 2.全量构建查询时不需要合并不同Segment,增量构建查询时需要合并不同Segment的结...

无精疯 ⋅ 26分钟前 ⋅ 0

如何将S/4HANA系统存储的图片文件用Java程序保存到本地

我在S/4HANA的事务码MM02里为Material维护图片文件作为附件: 通过如下简单的ABAP代码即可将图片文件的二进制内容读取出来: REPORT zgos_api.DATA ls_appl_object TYPE gos_s_obj.DA...

JerryWang_SAP ⋅ 44分钟前 ⋅ 0

云计算的选择悖论如何对待?

导读 人们都希望在工作和生活中有所选择。但心理学家的调查研究表明,在多种选项中进行选择并不一定会使人们更快乐,甚至不会产生更好的决策。心理学家Barry Schwartz称之为“选择悖论”。云...

问题终结者 ⋅ 51分钟前 ⋅ 0

637. Average of Levels in Binary Tree - LeetCode

Question 637. Average of Levels in Binary Tree Solution 思路:定义一个map,层数作为key,value保存每层的元素个数和所有元素的和,遍历这个树,把map里面填值,遍历结束后,再遍历这个map,把每...

yysue ⋅ 今天 ⋅ 0

IDEA配置和使用

版本控制 svn IDEA版本控制工具不能使用 VCS-->Enable Version Control Integration File-->Settings-->Plugins 搜索Subversion,勾选SVN和Git插件 删除.idea文件夹重新生成项目 安装SVN客户......

bithup ⋅ 今天 ⋅ 0

PE格式第三讲扩展,VA,RVA,FA的概念

作者:IBinary 出处:http://www.cnblogs.com/iBinary/ 版权所有,欢迎保留原文链接进行转载:) 一丶VA概念 VA (virtual Address) 虚拟地址的意思 ,比如随便打开一个PE,找下它的虚拟地址 这边...

simpower ⋅ 今天 ⋅ 0

180623-SpringBoot之logback配置文件

SpringBoot配置logback 项目的日志配置属于比较常见的case了,之前接触和使用的都是Spring结合xml的方式,引入几个依赖,然后写个 logback.xml 配置文件即可,那么在SpringBoot中可以怎么做?...

小灰灰Blog ⋅ 今天 ⋅ 0

冒泡排序

原理:比较两个相邻的元素,将值大的元素交换至右端。 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面。即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后。然后比较第...

人觉非常君 ⋅ 今天 ⋅ 0

Vagrant setup

安装软件 brew cask install virtualboxbrew cask install vagrant 创建project mkdir -p mst/vmcd mst/vmvagrant init hashicorp/precise64vagrant up hashicorp/precise64是一个box......

遥借东风 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部