[逻辑优化]C#中的字符串优化
一.string类
1.先看一下string类的定义
public sealed class String : IConvertible, IComparable, IEnumerable, ICloneable, IComparable<String>, IEquatable<String>, IEnumerable<char>
(1)sealed关键字:标识此类是密封的不能再被继承
(2)一系列的接口:接口规范了行为,标识着我们的类必须实现哪些方法,对于C#语言来说,接口是实现多继承的一种方式,而且可以提升代码的整洁程度,让我们醒目的看到子类中都有哪些方法
(3)一个特殊的私有变量:public static readonly String Empty,所有string的实例共享这个空字符串Empty,这也是为什么我们在使用空字符串比声明一个“”的字符串效率更高的原因(待考究)
(4)string继承自object,是引用类型
2.string类的特点
(1)每个实例都是单独的不可修改的,string c = string a + string b;会产生三个字符串实例,即a和b的拼接结果存储在c中,这就导致了string类的拼接效率非常的低,试想我们代码中的每个字符串都是独立存在的,而拼接后原字符串大概率是没什么用了,这种情况下我们代码中的垃圾内存会急剧上升,导致GC过早或者频繁触发,引起游戏卡顿
(2)C#中string类提供了大量的方法,方便我们使用,这里不一一列举,可在文档中查看
二.StringBuilder类
先付一个很详细的介绍stringbuilder类的博客
https://blog.csdn.net/snakorse/article/details/43900413
1.定义
public sealed class StringBuilder : ISerializable
StringBuilder的功能接口相对较少,主要是为了解决字符串拼接的效率问题,其中append函数可以将参数拼接到原有字符串,且不能保证所有实例成员都是线程安全的
2.几个关键参数
public int Capacity { get; set; }
public int MaxCapacity { get; }
public int Length { get; set; }
最大容量(MaxCapacity): 在构造StringBuilder对象时设定最大容量值,最大值一旦设定,将不可改变,如果Append或其它操作使Length大于MaxCapacity将抛出异常。
容量(Capacity):返回StringBuilder的当前容量,其取值范围为:0~MaxCapacity,这个属性是可读写的,若设置的值小于Length将抛出异常
长度(Length): 返回StringBuilder内部维护的当前String对象的长度,取值范围:0~MaxCapacity,可变属性
也就是说,Length是字符串实际的长度,Capacity是实际容量,当然Length不能小于Capacity,MaxCapacity是最大容量,默认值为int.MaxValue,即整数的最大值
3.优势
假如我们使用一个初始容量大小为255的StringBuilder那么在小于这个容量的任何append操作下,实际上都是对这个内存区域的修改和填充,而不是像string类那样产生新的字符串,避免了频繁的产生和回收内存,减少了垃圾的产生和游戏的卡顿。
4.依然存在的效率问题
正如所有需要连续内存的数据结构,List,Dictionary等,总会有一个初始容量大小,要么是我们手动设置的,要么是没有声明时使用的默认大小,那么就会有一个通用的问题,当当前内存区域大小不够需要我们进行扩容时,怎么办。无一例外,这些结构,包括stringbuilder在内,都是会开辟一个新的内存区域,然后把老的数据复制进去,那么原有的内存区域同样也变成了垃圾内存,数量过多的时候同样会触发GC引起游戏卡顿。而扩容的倍数默认通常是2倍,这也是为什么我们在使用这类数据结构的时候最好在声明的时候定义好容量的大小,也就是防止进行扩容产生内存垃圾
三.没有GC的字符串类
那么问题来了怎么实现一个没有GC的字符串,或者说更加高效的字符串类呢。
问题所在:
(1)拼接的时候不会产生新的实例
实现:在同一块内存上进行操作,无论是拼接还是替换或者删除
(2)扩容的时候不产生内存垃圾
实现:如果说扩容想在不产生新的内存的情况下,那么就要要求内存足够大,在我们进行扩容操作的时候无需申请新的内存空间,这样也就不存在老的内存会变成垃圾的情况;
总结实现:可以通过开辟一个内存区域使用C#中的指针,unsafe,在fixed中进行操作,自己控制超过容量时候要不要扩容,怎么扩容,从而优化字符串