特殊的string类型

1.前言

  string是属于引用类型的,这个大家都知道吧?但是平常在使用的过程中,发现它还是拥有一些值类型的特征的,这到底是为什么呢?

  原因就是.Net考虑到假如大量的操作string对象的时候,大量对引用对象进行操作的时候,性能肯定不如值类型来的爽快。.Net为了提高这个性能,提供了一个专门的解决方案:字符串驻留池!

 

2.正文

  先让我们来看一段代码:

1             string str1 = "aa";
2             string str2 = "a" + "a";
3             Console.WriteLine(ReferenceEquals(str1, str2));  //print:true

  这str1跟str2的内存指向地址居然是一模一样的!

  原因是.Net在CLR内部维护了一个Hash表(其实就是前文说的字符串驻留池),key为字符串内容,值就是所指向的托管堆的地址;当初始化创建了一个新的字符串的时候,.Net就会去这个Hash表中搜索是否有相同的值,如果key相同,就会把已经存在的字符串的地址值赋给新创建的字符串,如果不存在则重新分配地址,这就是为什么上面这个代码的内存为true。

 

  再让我们来看另外一段代码:

1             string str3 = "ab";
2             string str4 = "a";
3             str4 += "b";
4             Console.WriteLine(ReferenceEquals(str3, str4));//print :false

   之所以出现了false,请注意上一栏的关键字“初始化创建”,当字符串是动态创建的时候,.Net并不会去Hash表中搜索是否有创建,而是直接创建;

 

  假如想对上面的代码优化一下并且对性能有更(xian)高(de)追(dan)求(teng),我们可以手动将这个字符串加入到字符串驻留池中进行对比

1         string str3 = "ab";
2             string str4 = "a";
3             str4 += "b";
4             str4 = string.Intern(str4);//Intern:它会去字符串驻留池中搜索,假如找寻到的话则返回对应的地址
5             Console.WriteLine(ReferenceEquals(str3, str4));//print :true

 

3.总结

  最后对string下点结论:

    1.string在clr中不是用newobj指令创建,而是用ldstr指令创建!而且string拥有值类型的特征,但是在内存上是引用类型,存在托管堆上面;
    2.string是sealed修饰的,所以不能被子类集成;
    3.当创建内容相同的时候,string是指向同一地址的,而且每次操作string都会生成新的地址(string的恒定性);
    4.对于大量拼接的话还是使用StringBuilder,它是动态的不像string是恒定的,但就是创建StringBuilder代价比较大,所以小拼接用string在性能上可能还更好!

 

  还有最后一个最后,卖点小广告:深圳地区招聘.Net开发工程师(医疗方向),有兴趣的小伙伴可以发送简历 (入职后我们将推荐奖金拿去上梅林的潮兴火锅吃了吧~)

 

posted @ 2017-02-13 09:12  PowerDK  阅读(1209)  评论(12编辑  收藏  举报