深入理解.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的全部 ...
随机推荐
- Swift基础之UITabBarController(这是在之前UITableView中直接添加的)
这些基础内容基本已经可以搭建项目框架,剩下的就是一些优化,细节和数据请求问题,慢慢更新.... 在AppDelegate中创建方法 //创建方法执行UITabBarController func cr ...
- android动画介绍--Animation 实现loading动画效果
Animation的使用方法并不难.这里简单的介绍一下使用方法. 先看效果图: 效果还是不错的吧. 下面来看看使用方法. 动画效果是通过Animation来实现的,一共有四种,分别为: AlphaAn ...
- 命令行界面的C/S聊天室应用 (Socket多线程实现)
命令行界面即在Eclipe控制台输入数据. 服务器端包含多个线程,每个Socket对应一条线程,该线程负责读取对应输入流的数据(从客户端发送过来的数据),并将读到的数据向每个Socket输出流发送一遍 ...
- 仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字
仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Frag ...
- 【一天一道LeetCode】#9. Palindrome Number
一天一道LeetCode系列 (一)题目 Determine whether an integer is a palindrome. Do this without extra space. Some ...
- LeetCode之“数学”:Reverse Integer && Reverse Bits
1. Reverse Integer 题目链接 题目要求: Reverse digits of an integer. Example1: x = 123, return 321 Example2: ...
- linux的link命令
sudo ln -s 源文件 目标文件 sudo ln -s /usr/local/mysql/bin/mysqladmin /sbin/mysqladmin 建立软连接 ln -d existfil ...
- Oracle EBS 预警系统管理(可用于配置工作流发审批邮件)
本章主要讲述配置和设置Oracle EBS预警系统管理, 它比较方便和及时发用户或系统对数据库操作情况.下面讲一操作步聚: 1.预警系统管理-->系统-->选项 名称"Unix ...
- linux内核自旋锁API
我们大概都了解,锁这种机制其实是为了保护临界区代码的,关于使用和定义,我总结的API如下: #include <linux/spinlock.h> 定义自旋锁 spinlock_t loc ...
- win32多线程学习笔记
<多核程序设计技术> 第五章--线程api,一个使用windows事件的线程应用程序,vs2008下编译调试通过. // 线程通信机制.cpp : 定义控制台应用程序的入口点. // #i ...