[你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考
[2] [你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考
[3] [你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考
系列文章导航:
[你必须知道的.NET] 第四回:后来居上:class和struct
[你必须知道的.NET] 第五回:深入浅出关键字---把new说透
[你必须知道的.NET] 第六回:深入浅出关键字---base和this
[你必须知道的.NET] 第七回:品味类型---从通用类型系统开始
[你必须知道的.NET] 第八回:品味类型---值类型与引用类型(上)-内存有理
[你必须知道的.NET] 第九回:品味类型---值类型与引用类型(中)-规则无边
[你必须知道的.NET] 第十回:品味类型---值类型与引用类型(下)-应用征途
[你必须知道的.NET] 第十一回:参数之惑---传递的艺术(上)
[你必须知道的.NET] 第十二回:参数之惑---传递的艺术(下)
[你必须知道的.NET] 第十三回:从Hello, world开始认识IL
[你必须知道的.NET] 第十四回:认识IL代码---从开始到现在
[你必须知道的.NET] 第十六回:深入浅出关键字---using全接触
[你必须知道的.NET]第二十二回:字符串驻留(上)---带着问题思考
[你必须知道的.NET]第三十二回,深入.NET 4.0之,Tuple一二
什么是字符串驻留(String Interning)
回归经典,我们首先给出MSDN对于字符串驻留的一点讨论:
公共语言运行库通过维护一个表来存放字符串,该表称为拘留池,它包含程序中以编程方式声明或创建的每个唯一的字符串的一个引用。因此,具有特定值的字符串的实例在系统中只有一个。
例如,如果将同一字符串分配给几个变量,运行库就会从拘留池中检索对该字符串的相同引用,并将它分配给各个变量。
之所以,将string这个熟悉的命题拿出来造轮子,并不是再造个轮子自己陶醉。关于string的轮子,实在太多了,而且个个不顺眼,它就像编程的精灵,四处可见随处都有。string是如此的重要,以至于CLR必须以特殊的方式来实现对string类型的管理、存取和布局,在这些复杂的特殊表象中,字符串驻留机制是string特殊性的集中体现,它的基本原理可以概括为:
- CLR维护一个类似于哈希表的内部结构,用于维护对于字符串的统一管理。
- 但JIT编译时,CLR首先查找哈希表,如果没有找到匹配的字符串记录,则在托管堆中创建新的string实例,并为哈希表添加一个键值对记录;下一次查找相同string时,则只返回该记录的值给第二次创建的string对象。
- 通过这种方式,字符串驻留机制有效实现了对string的池管理,节省了大量的内存空间。
详细的字符串驻留机制,敬请参考:
快捷参考 |
关于字符串驻留机制的详细过程,不是本文所要解决的主要问题,你可以参考:
|
我们可以从code01尽情领略字符串驻留机制的基本原理,然而关于字符串驻留,并不是几句简单原理就能全面概括的问题。
注意:动态创建的字符串是不执行字符串驻留机制的,例如通过:
// Release : code09, 2008/08/25
// Author : Anytao, http://www.anytao.com
static void Main()
{
string s1 = "abc";
string s2 = "ab";
string s3 = s2 + "c";
Console.WriteLine(ReferenceEquals(s1, s3));
}
但是对于“动态”二字的把握并非一件简单的事情,什么情况下执行字符串驻留,而什么时候不会执行字符串驻留,在.NET spec中我并没有找出足够精确的正解来阐释这个问题,例如code06示例中,string s1 = GetStr(); 的位置很大程度上决定了是否执行字符串驻留条件,从code06示例的结果可见,string.IsInterned(s2)并未收获返回“abc”的预期结果,而下面的示例则又给出意想不到的答案:
// Release : code10, 2008/08/25
// Author : Anytao, http://www.anytao.com
static void Main()
{
//在这个位置返回abc
string s1 = GetStr();
string s2 = "ab";
s2 += "c";
Console.WriteLine(string.IsInterned(s2) ?? "null");
}
private static string GetStr()
{
return "abc";
}
对比code06和code10,我们发现不同的只是string s1 = GetStr(); 的位置,而结果却大相径庭。
为什么?
位置的不同而导致触发字符串驻留机制是否执行的条件不同,这正是我们通过实例反向验证的最佳体现。那么,你的思考呢?
这些看似熟悉的问题,其实都值得推敲,本文没有太多的精力兼顾所有,只能在边缘之余探讨一下遗留在字符串驻留机制中一些并不是很清楚的问题,算是对字符串驻留机制的进一步探讨,主要包括:
- CLR的加载过程。
- intern pool在什么时候创建,如何创建?
- 驻留机制的简述。
- 方法的调用过程。
- 介绍IsInterned和Intern方法。
- string intern的失效和弊端。
以解决本文开题的几个典型的问题,同时顺便解答KiMoGiGi在To 王涛 的问题中提出的问题。下面我们一一揭开这些问题的神秘面纱。
作为字符串驻留机制探讨的第一篇,我们从问题出发引出对于字符串驻留的定义和概念,在未来的篇章中除了说明上述问题之外,我们还将力图解释开篇8个示例的个中结果,并对可能的情况和问题进行一些对比性的推敲。
事实上,由string intern而引发的技术论题,还有很多值得我们品味和玩味,这也正是这个本文及其后续篇章力图做出的努力。
敬请期待,本篇后文。。。
特别鸣谢
Jeffery Richter,对于我的问题,Jeffery先生及时给出自己的见解,让我顿时感受到大师的品格。
KiMoGiGi,是他的问题带来本文的思考,这些难得的线索构成了我们进行探讨的基础话题,巧妇难为无米之炊,因此需要特别感谢。
参考文献
(Book)Martin Fowler,Refactoring: Improving the Design of Existing Code
(cnblog)http://www.cnblogs.com/flier/archive/2004/07/08/22307.html
(cnblog)http://www.cnblogs.com/artech/archive/2007/05/31/765773.html
© 2008 Anytao.com 原创作品,转贴请注明作者和出处,留此信息。