String — 深入理解String

String类型是我们常用的基础数据类型之一,他是一个特殊的引用类型,在.NET里面算是少有的异类,那么特殊在什么地方呢?接下来就让深入的了解String

一、特殊之处

     (1)、创建特殊性:String对象不能使用newobj指令创建,而是ldstr指令创建,在实现机制上,CLR给了特殊的照顾优化内存

     (2)、应用上,String类型表现为值类型,但在内存中,String类型表现为引用类型,存储在托管堆里面

     (3)、两次创建内容相同的String对象可以指向相同的地址

     (4)、String类是跨应用程序域的,可以在不同的应用程序域中访问到同一String对象

     (5)、String类是密封类,不能被继承

     (6)、因为字符串驻留是进程级别的,所以可以跨AppDomin存在,即同一个字符串对象可以在不同的应用程序域被访问,突破了AppDomin的隔离,其原因还是字符串的恒定性,因为是不可变的,所以没必要在隔离

二、字符串的恒定性

    string对象和其他类型最大的区别就是它的恒定性,指的是:字符串创建后,系统会在托管堆上开辟一块连续空间,我们无法通过人为的方式去修改它,所有对string类型操作的,实际上都是返回了一个新的string,其本身不产生任何差别。

    当然这样有利也有弊:利:保证原string对象的稳定性,不会出现线程同步问题。

                                弊:创建新的字符串对象,会消耗性能和内存。所以CLR使用了一项技术来解决这个问题——字符串驻留

三、字符串驻留

      先看代码

string s1 = "小红";
string s2 = "" + ""; 
string s3 = "";
string s4 = s3 + "";   
Console.WriteLine(ReferenceEquals(s1, s2));//ReferenceEquals():是Object的一个方法,比较引用是否相等,不要用于值类型比较
Console.WriteLine(ReferenceEquals(s1, s4));

执行结果:

答案是不是有点出乎意料?

    按理说,s1和s2是两个不同的string对象,为什么引用会相同呢?看结果就算是相同的,那么s4的值也是"小红",为什么和s1又不一样了?

好的,带着我们的问题,让我们首先来了解下什么叫做字符串驻留机制:

   对于相同的字符串,CLR不会为期重新分配内存空间,而是公用同一内存地址。

那么在内部CLR是怎么实现这一功能的?

     CLR内部维护了一个hash table 来管理其创建的大部分string对象。其中key是string本身,而value为分配给对应的string的内存地址。如下如所示

 

 现在我们在来回过头看一下那两个结果,为什么是true和false

第一个结果:s1和s2,在创建s1的时候,哈希表内的key并没有"小红"这个值,所以当JIT编译的时候,会在这个哈希表的key里面添加一个"小红",然后把s1在内存中的地址方法value里面,当创建s2的时候,JIT又在这个哈希表内进行查找,然后发现key里面已经有了这个值,所以,就把key-Value对应的value赋值给了s2,所以说他们两个的引用是相同的,那么为什么第二个结果是false呢?

第二个原因:虽然s4的结果最后也是"小红",但是在创建的过程中,发生了变化,s4是动态生成的字符串,这样的字符串是不会被添加到哈希表中进行维护的,所以返回为false。

这样,我们就能很容易的解释上述代码的原因了。

补充:对于动态生成的字符串,没有添加到CLR的哈希表中导致字符串驻留失效的,我们可以通过两个静态的string方法,手工启用字符串驻留机制

string s1="小红";
string s3="";
//s4 = string.Intern(s3+"红");  //true
s4 = string.IsInterned(s3+"");  //true
Console.WriteLine(ReferenceEquals(s1, s4));

public static String Intern(String str);

     //如果暂存了 str,则返回系统对其的引用;否则返回对值为 str 的字符串的新引用。

public static String IsInterned(String str);

    //此方法在暂存池中查找 str。 如果已经将 str 放入暂存池中,则返回对此实例的引用;否则返回 null。

两者的区别:

同样,如果我们不想使用字符串驻留机制,可以使用string.copy()来解除这一限定

string s1 = "小红";
string s2 = string.Copy(s1);
Console.WriteLine(ReferenceEquals(s1, s2));  //false

public static String Copy(String str);

 

特别指出:字符串驻留进程级别的,可以跨应用程序域(AppDomain)而存在,也就是不同的类里面相同的字符串值同样是同一个引用。垃圾回收不能释放哈希表中的引用字符串对象,只有进程结束这些对象才会被释放

  *根据《你必须知道的.NET》整理

转载于:https://www.cnblogs.com/whbk/p/6433554.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值