C#字符串浅析

    刚开博不久,就很想写点东西,但是出于种种原因都没动手。有了博客总不能空着,就在琢磨着写些什么。刚好学习了字符串的一些东西,做了下笔记感觉还不错,拿出来晒晒...
    先说说字符串操作的性能问题。C#中的字符串操作,用得也比较多,大家都不陌生。反正就是声明一个字符串变量,然后使劲地赋值,置空,再赋值(对一个字符串变量多次的赋值)。这时候会出现效率问题。why?其实字符串是一个不可变的数据类型,一旦对字符串对象进行了初始化,该对象就不能改变了。也就是说给字符串申请了一个空间,该空间就存在了,不会变化。如果再给字符串赋值,实际就是再申请一块空间,然后把原来的丢到,等待垃圾回收。举个例子:
string str=”hello! ”;
str+=”what is your name.”;
上述代码执行情况是:声明str时为str声明一个能够存储hello!的空间,然后把地址给str。执行+=时,把hello!与what is your name.合并,并申请一个能够存储合并后字符串的空间再把地址给str。先前声明存放hello!的空间,等待垃圾回收处理。
    再来谈谈StringBuilder类。StringBuiler通常分配的内存会比需要的更多。开发人员可以选择显式指定StringBuilder要分配多少内存,但如果没有显式指定,存储单元量在默认情况下就根据StringBuilder初始化时的字符串长度来确定。属性:
Length指定字符串的实际长度;
Capacity是字符串占据存储单元的最大长度。
对字符串的修改就在赋予StringBuilder实例的存储单元中进行,这就大大提高了添加子字符串和替换单个字符的效率。删除或插入子字符串仍然效率低下,因为这需要移动随后的字符串。当扩展字符串容量时,才需要给字符串分配新内存,才可能移动包含整个字符串。在添加额外的容量时,StringBuilder如果检测到容量超出,且容量没有设置新值,就会使自己的容量翻倍。StringBuilder并不总能提高性能。StringBuilder类基本上应在处理多个字符串时使用。但如果只是连接两个字符串,使用System.String会比较好。
    最后说下什么是字符串的复合格式设置。可能描述会有点多,现就自己说点,再引用点别人的东西《C#高级编程(6版)》,说明下复合格式设置中格式字符串是怎么解析的。格式字符串本身大都由要显示的文本组成,但只要有要格式化的变量,它在参数列表中的下标(下标放在{}中)就必须放在括号中。在括号中还可以有与该项的格式相关的其它信息:如
一、该项的字符串表示要占用的字符数,这个信息的前面应有一个逗号,负值表示该项应左对齐,正值表示该项应右对齐。如果该项占用的字符数比给定的多,其内容也会完整地显示出来(给定占用数比要显示的字符数大当然会全部显示)。
二、格式说明符也可以显示出来。它的前面应有一个冒号,表示应该按什么格式显示该项。
例如:Console.WriteLine(“The double is {0,10:E} and the int contains {1}”,d,i);
其中{0,10:E}中的0表示参数列表下标,10表示所占字符数,E表示格式说明符。
{0,10:E}表示第0个参数占用10个字符,并以科学计数法显示。
接下去看看,下面例子的解析过程:
Console.WriteLine(“The double is {0,10:E} and the int contains {1}”,d,i);
解析为:
String.Format(“The double is {0,10:E} and the int contains {1}”,d,i);
拆分为:
StringBuilder("The double is")//初始化
StringBuilder.AppendFromat("{0,10:E}",D)
StringBuilder.Append("and the int contains")
StringBuilder.AppendFromat("0",D)
Console.WriteLine() 只是把参数的完整列表传送给静态方法String.Format() .
String.Format()现在需要用对应对象的合适字符串表示 来替换每个格式说明符,构造最终的字符串.但是,对于这个建立字符串的过程,需要StringBuilder实例,而不是String实例.
示例中,StringBuilder实例是用字符串的第一部分(如The double is )创建和初始化。然后调用StringBuilder.AppendFormat()方法,传递第一个格式说明符“{0,10:E}”和相应的对象double,把这个对象的字符串表示添加到构造好的字符串中,这个过程会继续重复调用StringBuilder.Append()和StringBuilder.AppendFormat() 方法,直到得到了全部格式化好的字符串为止。
StringBuilder.AppendFormat()需要指出如何格式化对象,它首先检查对象,确定它是否执行System命名空间中的接口IFormattable.只要试着把这个对象转换为接口,看看转换是否成功即可,或者使用C#关键字is 也能实现此测试。(引用MSDN代码)
if (arg is IFormattable) s = ((IFormattable)arg).ToString(format, formatProvider);
else if (arg != null) s = arg.ToString();
如果测试失败,AppendFormat()只会调用对象的ToString()方法,所有的对象都从System.Object继承了这个方法或重写了该方法,而不会调用带有IFormattable参数的ToString()方法。
但是,所有预定义的基本数字类型都执行IFormattable这个接口,而不会调用继承自System.Object的基本ToString()方法。
      顺便介绍下IFormattable接口。IFormattable只定义了一个方法,该方法也叫做ToString() ,但它带有两个参数 ,而System.Object版本的ToString()不带参数。IFormattable定义如下:
Interface IFormattable
{
String ToString(string format,IFormatProvider formatProvider);
}
这是一个ToString()重载方法。其中,第一个参数是一个字符串,它制定要求的格式,放在{}中。在计算第一个说明符{0,10:E}时,在double变量(预定义的基本数字类型)d 上调用这个重载方法,它传递给它第一个参数E。StringBuilder.AppendFormat()传递的总是显示在原始字符串的合适格式说明符内冒号后面的文本;第二个参数是执行接口IFormatProvider的对象引用。这个接口提供了ToString()在格式化对象时需要考虑的更多信息——包括文化背景(.net文化背景类似于window时区,如果货币或日期的显示方式)。如果从源代码中直接到用这ToString重载方法,就需要提供IFormatProvider对象。但StringBuilder.AppendFormat()这个参数传递一个空值。如果FormatProvider为空,ToString()就要使用系统设置中指定的文化背景信息。
例如:Console.WriteLine(“The double is {0,10:E} and the int contains {1}”,d,i);
先拆解为StringBuilder.AppendFormat(“{0,10:E }”,d),由d调用具有两个参数的ToString重载方法(第一个参数为E,第二个参数是IFormatProvider类型但为空)。d调用完成后,再由StringBuilder.AppendFormat为d调用ToString返回后的字符串添加前导空格,以满足整个数值占10个字符位。对于i,因为其没有指定要显示的格式,故给该格式字符串传递一个空引用,并适当响应带有两个参数的ToString重载方法(也可以调用不带参数的ToString()方法)。

突然发现凌晨1点半了,睡觉,明天还要干活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值