C#基础之字符串Stirng特性详解
前言
今天是小僧第一次写博客,很是激动(昨天晚上做梦都是写博客)!小僧从事 .net工作,日常学习工作中接触了一些知识,
由于小僧年纪大了,怕忘记所学的知识,所以选择用博客的形式记录自己的学习心得,园子里面的各位大牛,多多指教!小僧写错的
地方,靠各位大牛指点出来,共同学习,共同进步,小僧坚信,代码虽不可以改变命运,但能填饱肚子,好了废话不多说,下面先讲
一下开发过程中用的最多的String字符串类型。
一、 String 是引用类型
首先唠叨一下:.net中数据分为值类型和引用类型。值类型包括:int,float,double...stuct ,enum;引用类型:自定义的类,数组,
string,集合,.net类库等(各位皮皮虾,这个问题面试经常问哦)。
二、String特性 不可变性
string虽然是引用类型,但是他又具有和引用类型不同的地方,那就是string的不可变性,空说无力,画张图先。。。。。。。。。
string a="hello" //当执行这段代码时,会在栈里开辟一块空间存储a变量,同时在堆中开辟一块空间存储"hello"值,此时栈中存储的是hello所在堆得地址 string a="hello pipixia" //当执行到这行代码的时候,不会覆盖原有堆上的Hello值,而是在堆上另外开辟了一块空间,存储新的值"hello pipixia",此时栈上a存储的是“hello pipixia”这块堆得地址了
字符串 对象一旦创建,在整个进程的生命周期中是不可变的,无法对其进行加长、缩短、改变等操作,既然它不会变,所以也就不存在线程同步
的问题,哪怕是皇天老儿创建的线程都无法对其进行改变。
三、字符串池子(驻留)
通过前面的描述,我们已经知道字符串的内存是分配在托管堆上,且它是不可改变的,而在编程中,我们会大量使用字符串,这就会导致不停地
创建字符串对象,不停地分配内存,并且很有可能不停地执行垃圾回收,如此以来会大大损伤性能,所以CLR对字符串进行了特殊的优化机制,下
面我们来对这些机制及特性进行描述。字符串驻留是CLR提供的一种提高性能的对待字符串的机制,它保证在一个进程内的某个字符串在内存中只
分配一次。看以下代码:
string str1 = "abc"; string str2 = "abc"; Console.WriteLine(object.ReferenceEquals(str1, str2)); //True
明明声明了两个对象str1和str2,调用object.ReferenceEquals方法返回的是True,为什么它们指向的是同一个引用呢?这就说明了CLR的字符
串驻留,相同的字符串在托管内存中只分配一次,再次声明相同的字符串对象时,会将后来一次的声明指向第一次声明所引用的对象。那么CLR 如何
保证做到的呢?原来,在CLR初始化时创建一个内部的哈希表,我们知道哈希表在处理表内数据时是非常快的,这个表相当于一个字典表(Dictionary<TKey,TValue>)
,键就是字符串,而值是指向托管堆中该字符串对象的引用,当在声明一个字符串时,会调用对象的Intern方法,该方法接收一个string对象,
它会先在哈希表中检查该字符串是否存在?如果存在,则返回这个字符串对应的对象引用;否则,将创建该字符串的副本,并将副本添加到哈希表中,
最后返回对该副本对象的引用。
四、StringBuilder
using System.Text; namespace StringBuilderDemo { class Program { static void Main(string[] args) { //stringbuilder没有不可变性,下面的代码指挥开辟一块内存 //stringbuilder是线程安全的,也就是说同一时间只允许一个线程访问,被LOCK了 StringBuilder sb = new StringBuilder(); for (int i = 0; i < 1000; i++) { sb.Append("i"); } sb.ToString(); } } }
实际开发过程中遇到这样的情况,请各位皮皮虾选择StringBuilder避免造成内存溢出问题!
总结:今天就写到这里吧,这些只是小僧自己的见解,写博客真的是个分享的过程,很激动,很开心,各位园友,多多指教!