string
1.一个string表示一个恒定不变的字符序列集合。
string直接继承自System.Object,这使得他成为一个引用类型,也就是说线程的堆栈上不会驻留有任何字符串。
注:
- 直接继承自Object的类型一定是引用类型;
- 所有的值类型都继承自System.ValueType,,但System.ValueType却是一个引用类型(public abstract class ValueType);
如下Code:
string s=new string("Hello");
无法通过编译。但是可以用
string s = new string(char[] chars);
string s = "Hello";
其中IL的指令 ldstr(即load string,加载字符串),该指令通过从元数据中获得的文本常量来构造string。
2.用+来连接字符串:
string s = "Hi"+" "+"there.";
由于所有的字符串都是文本常量字符串,所以编译器会在编译的时候就将他们连接为一个字符串,并将连接后的字符串放到生成模块的元数据中。
在运行时连接几个字符串(不是文本常量的字符串+操作),不建议使用+操作符。因为他会在要执行垃圾回收的托管堆上创建多个字符串对象。
3.字符串的恒定性
String对象最重要的特性便是其恒定性。一个字符串一旦被创建,我们就不能再将他变长,变短,或者改变其中任何的字符。
字符串的恒定性还意味着我们在操作字符串的时候不会出现线程同步问题。
如果两个字符串值相等的话,我们可以使两个字符窜引用指向同一个对象,而不必非要指向两个不同的字符串对象,这样可以减少系统中字符串的数量,从而节约内存,这也是
字符串驻留的机理。
4.字符串比较
5.字符串驻留
如果我们的应用程序频繁的对字符串进行判等操作,或者我们希望字符串对象都有相同的值,可以通过利用CLR中的字符串驻留(String Interning)机制来提高性能。
string s = "Hello"; Console.WriteLine(Object.RefenerceEquals("Hello",s));
当CLR初始化时,他会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串对象的引用。刚开始,该表为空。当JIT编译器编译方法时,它会在散列表中查找每一个文本常量字符串。对于上面的代码,编译器首先会查找第一个Hello字符串,并且因为他没有找到,就会在托管堆中构造一个新的string对象(指向该字符串),然后将Hello字符串和指向该对象的引用添加到散列表中。接着,JIT编译器在散列表中查找第二个Hello字符串,这一次由于会找到该字符串,所以不会执行任何操作。JIT编译将告完成,代码也开始执行。
当代码执行时,他会在第一行发现需要一个Hello字符串引用。于是,CLR便在其内部的散列表中查找Hello,并且会找到他,这样指向先前创建的String对象的引用就被保存在变量s中。当执行第二行代码时,CLR会在一次在内部的散列表中查找Hello,并且仍然会找到他。
如果有一种方法可以将含有相同字符集的动态字符串变为托管堆中的一个字符串对象的话,应用程序需要的对象也将减少,从而也可以提升系统性能。
String类型提供的两个静态方法允许我们做到这一点:
public static String Intern(String str); public static String IsInterned(String str);
- 第一个方法为Intern,他接受一个string参数,然后在CLR内部的散列表中查找他。如果能够找到该字符串,Intern将返回已经存在的string对象的引用;如果找不到该字符串,该字符串将被添加到CLR内部的散列表中,Intern最后也会返回他的引用。如果引用程序不再保存有原来string对象的引用,垃圾回收器将可以回收其所占的内存。
Note:
注意垃圾回收器不会释放CLR内部的散列表中引用的字符串对象,这些string对象的引用一直被散列表保存着。只有当进程中的所有应用程序域(APPDomain)都不在引用这些字符串对象时,他们才会被释放。这是因为字符串驻留是按进程为单位进行的,也就是说一个字符串对象可以被同一个进程中的多个应用程序域所访问。这也为我们得应用程序节省了不少内存。
- 第二个方法IsInterned,和Intern一样,会在CLR内部的散列表中查找他。如果CLR内部的的散列表中含有该字符串,IsInterned将返回散列表中保存的字符串的引用。如果散列表中不含该字符串,将返回null,他并不会将该字符串添加到散列表中。
6.字符串池(string pooling)
当编译源代码时,我们得编译器必须处理每一个文本常量字符串,并将其放入生成模块的元数据中。如果同样的文本常量字符串多次出现,编译器会在生成模块的元数据中只写入一次这样的字符串,然后将所有引用字符串的代码改变为引用元数据中的一个字符串。称之为字符串池,字符串池技术也是一种提高字符串处理性能的方法。