1.当有多个字符串变量包含了同样的字符串实际值时,CLR可能不会为它们重复地分配内存,而是让它们统统指向同一个字符串对象实例。 str01与str02的值相同,在对str02初始化的时候。并没有重新开辟内存,而是直接将地址指向str01的“wjg”。
string str01 = “wjg”;
string str02 = “wjg”;
//因为String类重载了==操作符来比较String对象包含的实际值
//所以不能用same=str01==str02
bool same = (object)str01 == (object)str02;
Console.WriteLine(same);//结果为True
Console.ReadKey();
字符串有不变性,一旦实例化完成就永远不会变了,我们每次对一个String对象进行操作时(比如说使用Trim,Replace等方法),并不是真的对这个String对象的实例进行修改,而是返回一个新的String对象实例作为操作执行的结果。 这样的话,CLR把我们的str01和str02共用一个地址就是合理的了,因为不管他们两个谁改变了,都不会影响到对方。这样可以优化内存。 为了维护这个机制,就出现了我们要说的驻留池,驻留池记录了所有在代码中使用字面量声明的字符串实例的引用。 这说明使用字面量声明的字符串会进入驻留池,而其他方式声明的字符串并不会进入,也就不会自动享受到CLR防止字符串冗余的机制的好处了,看第2条: 2.虽然str01和str02因为值相同所以指向同一个内存地址,但是并非2个值相同的字符串就对应同一个内存地址
string str03 = “jiangang”;
StringBuilder sb = new StringBuilder();
sb.Append(“jian”);
sb.Append(“gang”);
string str04 = sb.ToString();
bool SAME= (object)str03 == (object)str04;
Console.WriteLine(SAME);//结果为False
Console.ReadKey();
因为虽然str03,str04表示的是相同的字符串,但是由于str04不是通过字面量声明的,CLR在为sb.ToString()方法的返回值分配内存时,并不会到驻留池中去检查是否有值为jiangang的字符串已经存在了,所以自然不会让str04指向驻留池内的对象. 3.string.Intern方法:检索系统对指定 String 的引用。 在CLR中,维护名为暂存池中,包含对每个声明,或在程序中以编程方式创建的唯一字符串的单个引用的表,从而节约字符串存储区。 因此,具有特定值的文本字符串的实例仅一次系统中存在。 例如,如果将相同的文本字符串分配给几个变量,则运行时检索对文字字符串的相同引用从暂存池中,并将其分配给每个变量。 Intern方法使用暂存池中搜索的值相等的字符串_str_。 如果存在这样的字符串,则返回它在暂存池中的引用。 如果字符串不存在,对引用_str_添加到暂存池中,则返回该引用。 在下面的示例中,具有值为”MyTest”,字符串 s5 已经留用,因为它是在程序中的文本。 System.Text.StringBuilder类生成一个新的字符串对象,具有 s5相同的值。 该字符串的引用分配给 s6。 Intern具有相同的值为 s6的字符串方法搜索。 由于存在这样的字符串,该方法将返回分配给 s5 中的同一个引用。 然后,该引用被分配给 s7。 由于它们引用不同的对象; 因此,引用 s5 和 s6 比较不相等,引用 s5 和 s7比较结果相等,这是因为它们引用的相同的字符串。
string s5 = “MyTest”;
string s6 = new StringBuilder().Append(“My”).Append(“Test”).ToString();
string s7 = String.Intern(s6);
Console.WriteLine((Object)s6 == (Object)s5); //结果为False
Console.WriteLine((Object)s7 == (Object)s5); //结果为True
Console.ReadKey();
完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StringTemp
{
class Program
{
static void Main(string[] args)
{
string str01 = “wjg”;
string str02 = “wjg”;
//因为String类重载了==操作符来比较String对象包含的实际值
//所以不能用same=str01==str02
bool same = (object)str01 == (object)str02;
Console.WriteLine(same);//结果为True
//Console.ReadKey();
string str03 = "jiangang";
StringBuilder sb = new StringBuilder();
sb.Append("jian");
sb.Append("gang");
string str04 = sb.ToString();
bool SAME= (object)str03 == (object)str04;
Console.WriteLine(SAME);//结果为False
//Console.ReadKey();
string s5 = "MyTest";
string s6 = new StringBuilder().Append("My").Append("Test").ToString();
string s7 = String.Intern(s6);
Console.WriteLine((Object)s6 == (Object)s5); //结果为False
Console.WriteLine((Object)s7 == (Object)s5); //结果为True
Console.ReadKey();
}
}
}
结果如下: 官方文档:https://msdn.microsoft.com/en-us/library/system.string.intern(v=vs.110).aspx