C# 字符串操作

C#字符串操作

1.导读

本文主要讨论C#字符串操作时如何避免性能损耗。在此之前需要熟悉以下几个概念:

1)装箱和拆箱

装箱是将值类型转换为 object 类型或由此值类型实现的任何接口类型的过程. 当 CLR 对值类型进行装箱时,会将该值包装到 System.Object内部,再将后者存储在托管堆上。取消装箱将从对象中提取值类型。装箱是隐式的;取消装箱是显式的。

    关于装箱拆箱详细内容:http://msdn.microsoft.com/zhcn/library/yz2be5wk.aspx

2)IL代码

IL是.NET框架中中间语言(Intermediate Language)的缩写。使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但此时编译出来的程序代码并不是CPU能直接执行的机器代码,而是一种中间语言IL(Intermediate Language)的代码。IL语言的优点是只要把.NET框架某种语言(C#/VB)编译成IL代码,就实现.NET框架中语言之间的交互操作。

IL语言更多相信内容:http://www.cnblogs.com/xiaoxiangfeizi/archive/2011/08/08/2130768.html

3)托管与非托管

托管的意思,你不用直接操作内存,你需要的时候跟CLR说。CLR替你申请,然后给你用,你用完可以告诉CLR,CLR帮你释放,如果你忙,忘记告诉CLR了,CLR也会在定期去帮你释放的。这就是托管,你打交道的不是直接的内存,而是.net CLR。
    非托管的意思就是你要自己负责管理内存,这里所说的内存管理。实际上只是堆上的内存管理,栈内存和以前的一样,函数退出则释放,heap上的内存,非托管内存需要自己分配,调用构造函数(c需要,c++里用new替代这部操作了),使用完毕后,需要自己释放这个内存,如果你不小心,把指向内存的指针弄丢了,就造成内存泄露了,这个内存泄露在你程序退出之前是无法弥补的,所以要小心。

4)FCL与CLR

FCL:Framework Class Library,即Framework类库。

CLR(公共语言运行库,Common Language Runtime)和Java虚拟机一样也是一个运行时环境,是一个可由多种编程语言使用的运行环境。CLR的核心功能包括:内存管理程序集加载、安全性、异常处理线程同步,可由面向CLR的所有语言使用。并保证应用和底层操作系统之间必要的分离。CLR是.NET Framework的主要执行引擎。

更多关于CLR的内容请阅读《C# VIA CLR》

5)String和 StringBuilder

String在进行拼接操作时需要新开辟内存区域,为了弥补这个缺陷,微软提供了StringBuilder这个类型,StringBuilder开始以非托管形式分配内存,只有字符串长度大于默认初始长度时才会分配新的内存区域。

2.C#操作字符串的性能损耗

C#操作字符串的性能损耗通常来自于装箱,下面这两行代码中,第一行代码由于要进行装箱操作,性能比第二行低。

1 String str1 = “str1”+ 9;

2 String str2 = “str2”+9.ToString();

有人会质疑,ToString方法会不会存在装箱行为呢,我们来看看ToString方法的原型如下:

Public override StringToString()

{

   Retuen Number.Format32(m_value,null,NumberFormatInfo.CurrentInfo);

}

可能有人继续追问,是不是Number.Format32方法中存在装箱行为呢?事实上,Number.Format32是一个非托管方法:

[MethodImpl(MethodImplOptions.InternalCall),SecurityCritical]

Public static extern stringFormatInt32(int value,string format,NumberFormatInfo info);

它是通过直接访问内存来完成int到string的转换,效率要比装箱高得多,所以,在使用其他值引用类型到字符串的转换并完成拼接时,应当避免使用操作符“+”来完成,而应该使用值引用类型的ToString方法。

讨论到这里,有人会疑惑,在刚才讨论的例子中,FCL提供的方法中没有装箱行为,那是不是在其他任何情况下,FCL提供的方法中会不会存在装箱行为呢?答案是:可能会存在!不过,指导原则是:

在自己编写的代码中,应当尽可能地避免编写不必要的装箱代码;

这里补充说明下,装箱之所以会带来性能损耗,主要是由于装箱需要以下三个步骤:

1.  为值类型在托管堆中分配内存。除了值类型本身的内存外,还要加上类型对象的指针和同步块索引所占用的内存;

2.  将值类型的值复制到新分配的堆内存中;

3.  返回已经成为引用类型的对象的地址;

C#操作字符串性能损耗来自于额外的内存空间的分配。String类型对于CLR来说,一旦赋值就不可以改变,在运行时调用调用System.String的任何方法或进行任何计算(+,=)在内存中都会创建一个新的字符串对象,这意味着要为新的字符串对象分配新的内存空间。通常我们

采用StringBuilder类型来代替String类型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值