string interning
在CLR初始化时,会创建一个Hashtable,其中Hashtable的键为字符串,而它的值为托管堆中该字符串对象的引用,初始化时该Hashtable为空,当JIT编译器编译程序时,它就会在Hashtable中查找程序中的每一个字符串常量(即用Hashtable[字符串常量]的形式),如果没有对应的项,它就会在托管堆中创建一个新的string(指向该字符串),然后将字符串和指向该对象的引用添加到Hashtable中,当第二次出现这个字符串时,JIT编译器也会在Hashtable中查找,这次可以查到对应的项,那么,它就不会再做任何操作(不会再构造新的string指向这个字符串)。
例:string s = “Hello“;
Console.WriteLine(Object.ReferenceEquals(s, “Hello“));
由于上述的原因,例子的输出将为:True.
当一个字符串是动态创建的,而不是文本常量字符串,那么就不会出现以上请况.
例:string s = “Hello“;
string s1 = “Hel“;
string s2 = s1 + “lo“;
Console.WriteLine(Object.ReferenceEquals(s, s2));
以上输出为: False.
可以通过String的的static method将相同字符集动态字符串变为托管堆中的字符串对象。
1. public static string Intern(string str);
2. public static string IsInterned(string str);
其中1将到CLR内部的Hashtable中查找 否有以str为键的项,如有则返回它的引用,否则创建一个新的项,以str的值(字符串)为键,str的引用为值。
其中2同上,不同的是如找到返回它的引用,否则返回null。
注意:垃圾回收器不会释放CLR内部Hashtable中引用的字符串对象,只有当进程中所有的AppDomain都不再引用该对象,它们才会被释放,因为string interning是按进程为单位的。
例:string s = “Hello“;
Console.WriteLine(Object.ReferenceEquals(s, “Hello“));
由于上述的原因,例子的输出将为:True.
当一个字符串是动态创建的,而不是文本常量字符串,那么就不会出现以上请况.
例:string s = “Hello“;
string s1 = “Hel“;
string s2 = s1 + “lo“;
Console.WriteLine(Object.ReferenceEquals(s, s2));
以上输出为: False.
可以通过String的的static method将相同字符集动态字符串变为托管堆中的字符串对象。
1. public static string Intern(string str);
2. public static string IsInterned(string str);
其中1将到CLR内部的Hashtable中查找 否有以str为键的项,如有则返回它的引用,否则创建一个新的项,以str的值(字符串)为键,str的引用为值。
其中2同上,不同的是如找到返回它的引用,否则返回null。
注意:垃圾回收器不会释放CLR内部Hashtable中引用的字符串对象,只有当进程中所有的AppDomain都不再引用该对象,它们才会被释放,因为string interning是按进程为单位的。