现在的位置: 首页 > 综合 > 正文

每日一练 之 c#中的字符串驻留

2012年02月10日 ⁄ 综合 ⁄ 共 1735字 ⁄ 字号 评论关闭

 

无论在哪种语言与平台中,字符串都是我们最常使用的对象。
.Net与C#语言把字符串在表面上做的相当易用,但是只有在深入理解字符串在CLR的驻留形式后才能更加合理高效的使用字符串对象。

1 字符串的驻留形式
先看一个sample

        static void Main(string[] args)
        
{
            
//.Net Framework中将一个应用程序的string都存放在一个Hashtable中
            
//key就是值 value是堆地址

            
string str1 = "hello"//申请一块堆内存 把地址放在StringHashtable的key为hello的元素中
            string str2 = "hello";//由于上一句已经创建了key为hello的元素 所以不使用newobj 申请新的堆内存
            string str3 = "h" + "e" + "l" + "l" + "o"//编译成MSIL语言时 已经与string str3 = "hello"一样了
            string str4 = new string(new char[] 'h''e''l''l''o' }); //自己显示进行new

            
string str5 = "hello2"//申请一块堆内存 key为hello2


            Console.WriteLine(
object.ReferenceEquals(str1, str2).ToString()); //True 引用同一块堆内存
            Console.WriteLine(object.ReferenceEquals(str1, str3).ToString()); //True 也是引用同一块堆内存
            Console.WriteLine(object.ReferenceEquals(str1, str4).ToString()); //False 引用了不同的堆内存

            str2 
= "hello2"// 每次对字符串对象赋值时 都先从StringHashcode中检索是否有重复的key 检索到了str5

            Console.WriteLine(
object.ReferenceEquals(str1, str2).ToString()); //False str2与str1已经不引用同一个堆
            Console.WriteLine(object.ReferenceEquals(str2, str5).ToString()); //True 变成与str5引用同一个堆内存

            str1 
= Console.ReadLine();
            str2 
= Console.ReadLine();

            Console.WriteLine(
object.ReferenceEquals(str1, str2).ToString());
            Console.WriteLine(
object.ReferenceEquals(str1, string.Empty).ToString());

            Console.ReadLine();
        }

开始时候的str1,str2,str3其实在翻译为MSIL后,都是相同的string str = "hello";
然后该应用程序会有一个字符串池,应该是一个hashtable,保存着所有的字符串,后面的str2="hello2",使str2与str5指向了同一块内存。
最后我又试验了一下字符串池的机制是否在运行时也是启作用的,发现字符串池仅仅是编译时,优化了应用程序的大小,应用程序启动时,优化了内存占用大小,而运行时没有这个机制,每次对一个string的赋值都会导致在堆内存分配一块新的空间。

抱歉!评论已关闭.