C#String、string和stringBuider过程详细讲解

本文深入解析C#中String与StringBuilder的区别与使用场景,包括它们的数据存储方式、性能影响及内存管理策略。对比string的不可变性与StringBuilder的动态扩展特性,探讨不同操作下对性能的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

话不多说,直接走起

一、String

          小写:string        

           大写:String

    1.string类是C#中的类,而String是.net framework中的类
    2.如果写的是string,在编译的时候编译器会把他转换为String。所以直接使用String会让编译器少做工作,可以提高一下性能。
    3.使用string,如果是C#编译的话,比较规范。
    4.在c#中string是关键字,而String不是。
    5.使用String必须应用命名空间。
    6.string表示Unicode字符的字符串

二、string

举例说明:

c# ==》string a="aaa";

如上编码中,string a 表示新建一个string对象,已知string为引用类型,其存储数据的过程为:现在托管堆里开辟内存生成“aaa”,string a则把指针指向“aaa”对应的首地址;

c# ==》a=a+"ccc";

如上编码中,新生成两个对象分别是第一个a和“ccc”,过程为:先在托管堆里开辟内存创建“ccc”,后开辟内存创建第一个a,并把第二个a的值和对象“ccc”的值放入其中,最后把string a的指向指到最新的a对应的首地址。而之前的a和“aaa”对象则在托管堆中,等待GC的回收。

通过以上步骤得出的结论:

1.string对象的不可变性(string对象一经生成,在托管堆中的信息是不变的,改变的只是指针的指向)

2.堆string对象进行操作比较消耗性能,“+”操作就要多生成两个对象

3.当string达到一定长度时(好像是8000),数据会进入大托管堆,此时对对象进行操作时性能损耗会很大,因为他要在托管堆上开辟出一块足够大的内存来存放数据,若是找不到这样的位置,自然就报错了。另外,GC在进行内存回收时,针对小托管堆的回收频率肯定要比大托管堆的频率要高很多,也就是说GC对大托管堆的回收成本很高,也就形成了内存应用不合理的局面。

4.最大长度不超过int的最大值:2147483647(string.length是int型)

5.线程安全

三、stringbuider

stringbuider分为两部分:

首先是.Net2.0版本:

stringbuider  a=new stringbuider("aaa");

首先先在托管堆默认开辟默认初始容量16的内存生成“aaa”,并把A指向他

a.append("bbbbb");

若“aaa”+"bbbbbb"长度小于“aaa”容量,则直接添加进去,若“aaa”+"bbbbbb"长度大于“aaa”容量且小于“aaa”容量的2倍,则开辟2*“aaa”容量,若“aaa”+"bbbbbb"长度大于“aaa”容量的两倍,则开辟“aaa”+"bbbbbb"长度的容量,后者一次类推。(我们设两字符长度分别为a、b,若a+b<a.容量,直接添加;若a.容量<a+b<2*a.容量,开辟2*a.容量内存;若2*a.容量<a+b,开辟a+b容量内存)。开辟内存过后,将aaa复制到该内存并追加上”bbbbbb“,完成后将a指针指向该内存,旧的a则在堆中等待GC回收

以上步骤总结:

1.对象不可变形,和string类似都是改指针地址,旧内存等待回收

2.每次append之生成1个对象,也会出现和string相同的问题,当进入大托管堆是很耗性能且会有内存分配错误的问题

3.存在额外的性能消耗(信息拷贝,内存分配)

 

.Net4.0版本

stringbuider  a=new stringbuider("aaa");

首先先在托管堆默认开辟默认初始容量16的内存生成“aaa”,并把A指向他

a.append("bbbbb");

若设两字符长度分别为a、b,若a+b<a.容量,直接进行追加操作,若a.容量<a+b<8000-a.长度,开辟a+b-a.长度(“a+b-a.长度”按照.net2.0规则进行内存容量计算)内存容量,并把a.容量末尾指针指向新开辟内存地址,形成链表,若a+b-a.长度>8000,则分别开辟8000长度内存和a+b-a.长度-8000长度内存,并将其首尾相连形成链表。

总结:

1.首次分配容量默认为16长度

2.相比较.Net2.0,性能更高(缺少了复制原对象内存的过程)

3.始终在小托管堆上,GC效率更高

4.因为是链表的方式,且容量扩展时开辟的内存比较小,所以出现找不到区域开辟内存的几率很小

5.默认最大容量是Int32.MaxValue

6.非线程安全

 

ok,讲解到此为止!!!如有疑问或者错误,请大家提出和指正~~~

 

 

参考:https://www.cnblogs.com/leo7718/p/3760256.html

https://docs.microsoft.com/zh-cn/dotnet/api/system.text.stringbuilder?redirectedfrom=MSDN&view=netframework-4.8#HowWorks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值