首先,咱们要知道的是String类型是一个引用类型,它的基类是Object。而且它的内容是只读的。spa
咱们有时候常常会看到两个字符串类型,一个是“Sting”,一个是“string”。大写的String是System.String,也就是 公共语言规范(Common Language Specification) CLS 所定义的字符串类型;小写的string则是C#本身的字符串类型;最终C#编译器仍是会把它和System.String联系起来。code
例如:对象
string a = "a"; a = "abc";
咱们来简单分析下这两段代码:blog
1.第一段代码,首先会在托管堆上分配一块内存,用来存储“a”,而后将该对象的首地址保存到变量a中。(若是驻留池中有“a”,就能够直接取出)进程
2.第二段代码,会在托管堆上从新分配一块内存,用来储存“abc”,而后修改变量a的值,使它指向该对象的首地址。内存
须要注意的是,string类型提供了许多的静态和实例的方法,好比ToUpper,Concat等;这些方法都返回一个新的字符串。这些新的字符串要么是新建的,要么是从字符串驻留池中去出来的,与原字符串无关。ci
好了,如今让咱们来看看“字符串驻留池”(Intern Pool)。顾名思义,凡是看到什么什么池之类的东西,都能猜到字面确定存着许多对象,就是为了反复使用,避免咱们本身从新new。每一个进程都有本身的字符串驻留池,因此i它们之间互不影响。字符串
咱们先来看一个例子:编译器
string a1 = "a"; string a2 = "a"; //"a"已经存在于驻留池中,直接取出 string a3 = new string('a', 1); Console.WriteLine(ReferenceEquals(a1, a2)); Console.WriteLine(ReferenceEquals(a1, a3));
咱们运行完这段代码以后就能够获得,第一输出True,第二个输出False。输出True,是由于直接使用的驻留池中的字符串;可是为何第二个输出是False呢?string
由于:CLR在程序执行的时候,首先会把嵌入到源代码中的文本常量字符串加入到“字符串驻留池”中;可是,程序中动态建立的字符串却不会被加入。