一、正确操作字符串
提示:不正确的使用字符串会导致额外的性能开销。
1.不恰当的字符串使用方法
代码如下(示例):
string s1 = "abc";
s1 = "123" + s1 + "456";
以上两行代码创建了3个字符串对象,并执行了一次 string.Contact 方法。
上述代码产生了额外的开销,对CLR来说,string对象一旦被赋值就不可改变。在运行时调用 System.String 类中的任何方法或者进行任何计算(如 "=“赋值、”+"拼接等),都会在内存中创建一个新的字符串对象,即要为该新对象分配新的内存空间。
string str1 = "123" + "abc" + "456";//该代码等效于
// string str1 = "123abc456";
const string a = "t";
string str2 = "abc" + a;//因为 a是常量,所以该行代码等效于
//string str2 = "abc" + "t";
//也等效于
//string str2 = "abct";
上述代码中,字符串不会在运行时拼接字符串,而是在编译时直接生成一个字符串。
string str1 = 9 + "456";
string str2 = 9.ToString() + "456";
str1产生一次装箱,并调用一次 string.Contact 方法。
在使用其他值引用类型到字符串的转换时,应该使用值引用类型提供的 ToString 方法,减少装箱操作。
2.恰当的字符串拼接方法
使用StringBuilder类型来弥补String的不足。
StringBuilder默认分配的长度为16。
- StringBuilder字符长度<16,StringBuilder不会重新分配内存;
- 16<StringBuilder字符长度<32,StringBuilder重新分配内存,使之成为16的倍数;
如果预先判断字符串的长度大于16,则可以设定一个更加合适的长度(如32)。StringBuilder分配内存时按照上次的容量加倍进行分配的。注意,如果StringBuilder指定的长度太小了,需要频繁分配内存,如果太大了,浪费空间。
代码如下(示例):
string a = "t";
a += "e";
a += "s";
a += "t";
string result = a;
string a = "t";
string b = "e";
string c = "s";
string d = "t";
string result = a + b +c + d;
上述的两种方法效率都不高。两者创建的字符串对象相等,前者比后者多用了两次string.Contact。
用StringBuilder实现上述操作如下:
string a = "t";
string b = "e";
string c = "s";
string d = "t";
StringBuilder sb = new StringBuilder(a);
sb.Append(b);
sb.Append(c);
sb.Append(d);
string result = sb.ToString();
另外提供一个方法进行简化该操作,即string.Format的方法。string.Format方法在内部使用StringBuilder进行字符串的格式化,代码如下:
string a = "t";
string b = "e";
string c = "s";
string d = "t";
string result = string.Format("{0]{1}{2}{3}",a,b,c,d);
总结
在使用字符串的拼接和转换时,应尽量避免使用"+"和装箱操作,拼接使用 String.Format,转换使用 .ToString()。