小新的技术天地

Make It Works !

博客园 首页 新随笔 联系 订阅 管理
String s = “Hello”;
Console.WriteLine(Object.ReferenceEquals(“Hello“,s));

你猜显示是true还是false,很多人会猜false,你看,不是有两个“Hello”对象吗?可实际上应该是true,为什么呢?下面解释一下:

其实CLR初始化时,他会创建一个内部散列表,键为字符串,值为指向托管堆中字符串对象的引用。刚开始这个表是空的。当JIT编译器编译方法时,它会在散列表中查找每一个文本常量字符串。现在看一下上面的代码,JIT先在散列表中查找第一个“Hello”,没有找到,它便在托管堆中构造一个新的String对象,然后将“Hello”字符串和指向该对象的引用添加到散列表中。接着,JIT在散列表中第二次查找“Hello”,这次找到了,就不进行其它操作了(不在构造其他String对象了)。

当代码执行时,它会在第一行发现一个需要“Hello”字符串引用。于是,CLR在其内部散列表中查找“Hello”,找到了,那样,我们此前创建的String对象(请参见前面的红字)的引用就被保存在变量s中。,当执行第二行代码时,CLR又去散列表中找“Hello”了,然后找到了。然后,只想同一String对象(请参见前面的红字)的引用被传递给Object.ReferenceEquals的第一个参数,当然返回true了。

当一个引用字符串的方法被JIT编译时,所有嵌入在源代码中的文本常量字符串总会被添加到CLR内部的散列表中。那么动态创建字符串呢?又会怎么样?

要吃饭了,吃完饭回来写续,哈。

注:此文参考《.NET框架程序设计(修订版)》


posted on 2004-10-27 10:58  小新0574  阅读(1844)  评论(9编辑  收藏  举报