本文共 1894 字,大约阅读时间需要 6 分钟。
本次字符串拘留实验分为4个,最终根据实验得出了一个很有意思的结论。这些结论使兄弟们在以前关于字符串操作的结论基础上进行深入理解。(关于字符串拘留池,请Google一下String Intern Pool,你可以搜索到不少东西的。)
1 在Main中没有出现硬字符串
string a1 = new string('a', 1);
string a2 = new string('a', 1);
Console.WriteLine(a1);
Console.WriteLine(string.IsInterned(a1) != null);
Console.WriteLine(ReferenceEquals(a1, a2));
> a
> False
> False
2 在Main中出现硬字符串
string a1 = new string('a', 1);
string a2 = new string('a', 1);
Console.WriteLine(a1);
Console.WriteLine(string.IsInterned(a1) != null);
Console.WriteLine(string.IsInterned("a") != null);
Console.WriteLine(ReferenceEquals(a1, a2));
> a
> True
> True
> False
注意:为什么第一个IsInterned竟然得出a已经拘留了呢?呵呵。
3 在Main中不出现硬字符串,但在另一个类出现硬字符串,不过另一个类没有被使用
// a1 和 a2都不在拘留池,且地址不一样。
string a1 = new string('a', 1);
string a2 = new string('a', 1);
Console.WriteLine(a1);
Console.WriteLine(string.IsInterned(a1) != null);
Console.WriteLine(ReferenceEquals(a1, a2));
class StringInternPoolTest1
{
public StringInternPoolTest1()
{
string a1 = new string('a', 1);
Console.WriteLine(string.IsInterned(a1) != null);
string a = "a";
}
}
> a
> False
> False
4 在Main中不出现硬字符串,但使用了另一个具有硬字符串的类
string a1 = new string('a', 1);
string a2 = new string('a', 1);
Console.WriteLine(a1);
Console.WriteLine(string.IsInterned(a1) != null);
Console.WriteLine(ReferenceEquals(a1, a2));
StringInternPoolTest1 test = new StringInternPoolTest1();
class StringInternPoolTest1
{
public StringInternPoolTest1()
{
string a1 = new string('a', 1);
Console.WriteLine(string.IsInterned(a1) != null);
string a = "a";
}
}
> a
> False
> False
> True
本次实验结论:
1 只有硬字符串才能被拘留;
2 当JIT编译方法后,执行前会将一个方法的所有硬字符串拘留;
3 string x = "a" 不会执行内存分配,原因很简单,在该语句之前JIT已经执行字符串拘留,即JIT提前分配了字符串的所需的内存以及字符串拘留池项。
其它待实验论点:
1 只有CLR执行结束,拘留字符串才能被释放;
2 拘留一个字符串的行为为将引用添加到CLR的一个Hashtable,它始终对字符串进行引用,从而阻止GC对拘留字符串进行回收;
3 编译器的优化行为(大家可以猜测一下如何优化,呵呵)。
本文转自道法自然博客园博客,原文链接:http://www.cnblogs.com/baihmpgy/archive/2010/03/02/1676842.html,如需转载请自行联系原作者