深入理解.net - 4.你必须知道的String
为什么要单独写string,主要是它太常用了,同时又太特殊了,特殊到CLR对它的处理都和其它对象不一样。简直可以称为VIP用户啊。本文并不是一篇介绍如何使用string的文章,而是旨在阐述string的一些本质特性。
引用类型
首先要明确string对象是引用类型的,具有引用类型一切特征,上篇文章也写了关于引用类型的的一些知识,有兴趣的可以看看。引用类型是创建在堆上的,默认是按值传递的。按这个理论来看string就有一些有意思的现象了。
public static void ChangeStringValue(string tmp)
{
tmp = "bbb";
}
public static void Main(string[] args)
{
string str = "aaa";
ChangeStringValue(str);
Console.WriteLine(str);
}
上面代码基本上会写程序的人都知道输入的结果是:aaa
但是string身为一个引用类型调用ChangeStringValue方法时传递的应该是Main方法中str变量的值(即对象实例的引用)啊,在此强调一点就是引用类型和值类型一样默认都是按值传递的。输出的结果为什么不是 bbb 呢?
答案就是:Immutable
恒定不变的(Immutable)String
MSDN上是这么介绍的:
A String object is called immutable (read-only), because its value cannot be modified after it has been created. Methods that appear to modify a String object actually return a new String object that contains the modification.
大体意思就是说:string对象是不变的或只读的,因为创建之后它的值是不能修改的。表面上修改一个string对象实际上返回的是一个包含了修改内容的新的string对象。
所以呢,每次修改string变量其实都是新建了一个string对象。
将上述代码的简单内存模型所示如下:

so,当我们调用ChangeStringValue方法时,传递的确实是string对象的引用,此时变量tmp和str存储的都是"aaa"字符串的引用,
但是由于string的Immutable特殊性,当我们执行tmp= "bbb"; 时,CLR会先创建了一个新的字符串"bbb",然后将ChangeStringValue方法的参数tmp的值修改成字符串"bbb"的引用了。但Main方法中的变量str的值并没有被改变还是指向字符串"aaa"的。所以输出的结果是:aaa
通常我们使用引用类型时,对引用类型的操作是会直接影响到外部的对象的,但由于Immutable特性,string对象的值是无法修改的,为什么要这么设计呢?这又牵扯出另一个有意思的特性。
字符串的驻留(String Interning)
什么是驻留呢,大牛们讨论了很多我就不卖弄了,引用下Artech大神 《再说String》文章中的一段描述如下:
String的驻留机制实际上是在SystemDomain中进行的。当CLR被加载之后,会在SystemDomain对应的managed heap中创建一个Hash table的数据结构,我们可以称这个Hashtable为Interning table,因为它是被用来保存被驻留的string的,Interning table的Key为string本身,Value为string对象的地址。
当我们的托管程序(无论对于那个AppDomain)需要一个string的时候,CLR首先在这个Hashtable根据这个string的hash code试着在Interning table中找对应的Item。如果成功找到,则直接把对应的引用返回,否则就在SystemDomain对应的managed heap中创建该string,并加入到Interning table中,并把引用返回。所以我们说字符串的驻留是基于整个进程的,是可以跨AppDomain共享的,就是这个道理。
显而易见,lock一个string对象是多么恐怖的事情;大量的字符串拼接也是非常浪费性能的,推荐使用StringBuilder。
总结
string是个引用类型,string Immutable,String Interning,这些都是你必须要知道的。臭不要脸的借用了下大神的书名,致敬下经典。
末尾参考链接吐血推荐一波,绝对看的爽歪歪,相信你会收获到更多。
参考链接
- 《你必须知道的.NET》
- String Class - MSDN
- 字符串的驻留(String Interning)- Artech
- 深入理解string和如何高效地使用string - Artech
- 再说String - Artech
- 关于String的终极解释
深入理解.net - 4.你必须知道的String的更多相关文章
- 【源码分析】你必须知道的string.IsNullOrEmpty && string.IsNullOrWhiteSpace
写在前面 之前自信撸码时踩了一次小坑,代码如下: private static void AppServer_NewMessageReceived(WebSocketSession session, ...
- 必须知道的String知识点
1.String 类型的概述 Java中String就是Unicode字符序列,例如,字符串"Java\u2122"由5个Unicode字符J.a.v.a和 ™ 组成.不像C/C+ ...
- Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor
Webservice WCF WebApi 注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...
- C#刨根究底:《你必须知道的.NET》读书笔记系列
一.此书到底何方神圣? <你必须知道的.NET>来自于微软MVP—王涛(网名:AnyTao,博客园大牛之一,其博客地址为:http://anytao.cnblogs.com/)的最新技术心 ...
- (转)【推荐】初级.NET程序员,你必须知道的EF知识和经验
转自:http://www.cnblogs.com/zhaopei/p/5721789.html [推荐]初级.NET程序员,你必须知道的EF知识和经验 阅读目录 [本文已下咒.先顶后看,会涨 ...
- Apple的App Analytics统计平台你必须知道的Q&A整理与翻译
Apple的App Analytics统计平台你必须知道的Q&A整理与翻译 Apple最近在iTunesConnect里最新发布了App Analytics统计平台,提供了现有友盟统计平台和自 ...
- [你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理
原文地址:http://kb.cnblogs.com/page/42318/ 系列文章导航: [你必须知道的.NET] 开篇有益 [你必须知道的.NET] 第一回:恩怨情仇:is和as [你必须知道的 ...
- [你必须知道的.NET]第三十一回,深入.NET 4.0之,从“新”展望
发布日期:2009.05.22 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. /// <summary> /// 本文开始,将以& ...
- 《jQuery风暴》第2章 必须知道的JavaScript知识
第2章 必须知道的JavaScript知识 JavaScript是jQuery应用的基础,掌握JavaScript这门语言是使用jQuery的基础条件.本章不会全面细致的讲解JavaScript的全部 ...
随机推荐
- mpi中的广播
MPI可以实现一对多的集合通信,最常用的是广播:某个进程将数据广播到所有其他进程,最终的结果就是每个进程都有一份广播的数据.MPICH中的广播函数是MPI_Bcast(void* buffer,int ...
- javascript 实战总结
JavaScript的简单的知识前面已经总结 欢迎交流学习,学习靠的是理论+实践, 通过姜昊老师的JavaScript专题训练,加深了对理论知识的理解,学习新的语言越来越发现熟悉的背景,基础内容是 ...
- Dynamics CRM Odata QueryUrl中的SetName问题
用javasrcipt通过odata方式访问组织服务进行CRUD操作时,queryurl的正确拼接很关键. 以下面的url为例:"XX/XRMServices/2011/Organizati ...
- MySQL学习笔记_10_MySQL高级操作(下)
MySQL高级操作(下) 五.MySQL预处理语句 1.设置预处理stmt,传递一个数据作为where的判断条件 prepare stmt from "select * from table ...
- C#之概述
当前流行的开发语言概述 C#是微软公司为Visual Studio开发平台推出的一种简洁.类型安全的面向对象的编程语言,开发人员可以通过她编写在.NET Framework上运行的各种安全可靠的应用程 ...
- 22_Android中的本地音乐播放器和网络音乐播放器的编写,本地视频播放器和网络视频播放器,照相机案例,偷拍案例实现
1 编写以下案例: 当点击了"播放"之后,在手机上的/mnt/sdcard2/natural.mp3就会播放. 2 编写布局文件activity_main.xml <Line ...
- 青年之锋文学网( www.xcqnzf…
青年之锋文学网( www.xcqnzf.com )简介: 青年之锋文学网创建于2013年秋,是河南农业大学(应用科技学院)--青年之锋文学社的官方网站,网站以长篇写作和出版校刊为主题,短篇精彩丰富为中 ...
- 在FFMPEG中使用libRTMP的经验
FFMPEG在编译的时候可以选择支持RTMP的类库libRTMP.这样ffmpeg就可以支持rtmp://, rtmpt://, rtmpe://, rtmpte://,以及 rtmps://协议了. ...
- SpriteBuilder代码中弱引用(weak)需要注意的地方
比如在GameScene类中有一个弹出菜单层实例的引用,我们有: @implementation GameScene{ //other ivars __weak GameMenuLayer *_pop ...
- Mybatis的resultType
使用mybatis去查询数据时,没有指定resultType,mybatis无法返回正常结果,当然在web中并没有出现报错,所以有点坑自己了,所以需要使用如下配置: <select id=&qu ...