C#中如何正确的使用字符串String

2020-01-05 10:03:10王冬梅

 

第二个方面:避免分配额外的空间。对于CLR来说,String对象(字符串对象)是个很特殊的对象,它一旦被赋值就不可改变(在内存中)。在运行时调用System.String类中的任何方法或进行任何运算('=‘赋值,'+‘拼接等),都会在内存中创建一个新的字符串对象,这也意味着要为该新对象分配新的内存空间。如以下代码会带来额外开销。


private static void Test(){
   String str1 = "aa";
  str1 = str1 + "123" + "345";
   //以上代码创建了3个String对象,并执行了一次String.Contact方法。
}

而在以下代码中,字符串不会在运行时拼接字符串,而是会在编译时直接生成一个字符串。


private static void Test()
{
String str= "aa" + "123" + "345";//等效 String str= "aa123345";
}

private static void Test2()
{
const String str = "aa";
String newStr = "123" + str;
//因为str是一个常量,所以该代码等效于 String newStr = "123" + “aa”;
//最终等效于 String newStr = "123aa”;
}

由于使用System.String类会在某些场合带来明显的性能损耗,所以微软另外提供了一个类型StringBuilder来弥补String的不足。

StringBuilder并不会重新创建一个String对象,它的效率源于预先以非托管的方式分配内存。如果StringBuilder没有先定义长度,则默认分配的长度为16。当StringBuilder的长度大于16小于32时,StringBuild又会重新分配内存,使之成为16的倍数。StringBuilder重新分配内存时按照上次的容量加倍进行分配的。注意:StringBuilder指定的长度要合适,太小了,需要频繁分配内存;太大了,浪费内存空间。

以下是例子举例:


private static String Test3()
  {
   String a = "t";
   a += "e";
   a += "s";
   a += "t";
   return a;
  }
  private static String Test4()
  {
   String a = "t";
   String b = "e";
   String c = "s";
   String d = "t";
   return a + b + c + d;
  }
  //以上两种效率都不高效。不要以为前者比后者创建的字符串对象更少,事实上,两者创建的字符串对象相等
  //且前者进行了3次的String.Contact方法调用,比后者还多了两次。