【c#基础】字符串的不可变性和驻留机制
.堆的分配向高地址扩展,栈的分配向低地址扩展。
字符串的不可变性(恒定性):
当你给一个字符串重新赋值之后,老值并没有被销毁(覆盖),而是重新开辟了一块空间存储新值IL(中可以查看)
所以我们使用字符串扩展方法时,其实都是一个新的对象(Trim)
字符串的驻留机制
//CLR中维护着一个驻留池(Intern Pool)的散列表(HashTable),这个表记录了所有在代码中使用字面量声明的字符串实例的引用
//使用字面量声明的字符串都会被记录到散驻留池(散列表 键为字符串 值为字符串存储地址)
从下图我们可以看出str和str1在堆中的地址是一样的,而在栈中地址是不一样的。
什么是字面量?
//字面量是源代码中书写的数字或字符串,用来表示一个明确类型的明确、固定的值。
//字符串字面量(string literal)是指双引号引住的一系列字符,字符串字面量使用双引号标记
如:string str="abc"; 或 string str="a"+"bc"这种就可以称为字面量
但是 string str=变量+变量 或者 变量+字符串 这种都不能称为字面量
//Intern方法接受一个字符串作为参数,它会在驻留池中检查是否存在参数所表示的字符串。
//如果存在,则返回那个驻留池中的字符串的引用;否则向驻留池中加入一个新的表示相同值的字符串,
//并返回这个字符串的引用。不过要注意的是,就算Intern方法在驻留池中找到了相同值的字符串,
//也不能让您省却一次字符串内存分配的操作,因为作为参数的字符串已经被分配了一次内存了。
//而使用Intern方法的好处在于,如果Intern方法在驻留池中找到了相同值的字符串,
//此时虽然在内存中存在两份该字符串的副本(一份是参数,一份是驻留池中的),
//参数所引用的那个副本会被垃圾回收掉,这样对于该字符串内存中就不存在冗余了。
string.Intern 和string.IsInterned区别
Intern:判断我们要加的字符串是否在驻留池中,如果驻留池中存在就返回引用,如果不存在就加入驻留池中并返回引用
IsInterned:判断字符串是否在驻留池中,如果在就返回引用,不存在就返回null.
//正是字符串的恒定性,才造就了字符串的驻留机制,
//也为字符串的线程同步工作大开方便之门(同一个字符串对象可以在不同的应用程序域中被访问,
//所以驻留的字符串是进程级的,垃圾回收不能释放这些字符串对象,只有进程结束这些对象才被释放)。