首先理解string,String,StringBuilder的概念和区别:
string
string,msdn给出的解释就是,string 是C#中的关键字,并且是引用类型, string类型表示零或更多Unicode 字符组成的序列。string 是 .NET Framework 中 String的别名。但定义相等运算符( 和!=)是为了比较 string 对象(而不是引用)的值(后面给出示例解释这点)。
String:
String是类,表示文本,即一系列 Unicode 字符。String 对象是不可改变的。每次使用System.String类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。如:当我们实例化一个String的对象后,在内存中为此对象分配一个空间。如下:Stringstr= “hello”;当我们修改str的值的时候,如:str =“helloworld”;此时,系统会为str重新分配一个空间。这样原来的内存空间就被浪费掉了,只能等待垃圾回收器回收。在需要对字符串执行重复修改的情况下,与创建新的String对象相关的系统开销可能会非常昂贵。
String与string的区别:
string 是 .NET Framework 中String的别名,string是C#基元类型(primitive),简单来说就是编译器直接支持的数据类型。基元类型要直接映射到Framework类库(FCL)中的类型,例如,C#中一个基元类型int直接映射到System.Int32类型,这里int是基元类型,System.Int32是FCL类型。而String是FCL类型的,所以在C#的编译时,会自动的把string转化为System.String。所以string与String实质上没什么区别,只是在使用string要做一次转换,转换为String。因此,在编码时我们推荐使用String。
string虽然为引用类型,但是( 和 !=)是为了比较 string 对象(而不是引用)的值。
如:
string a = hello;
string b = hel;
b = b + lo;
string c = hello;
Response.Write(ab); //True
Response.Write((t)a (t)b); //False
Response.Write((t)a (t)c); //True
ab比较的是值而非引用。所以ab为True。当创建多个字符串内容相同的对象时,都只会指向同一个引用;a和c都指向同一个a的引用,并不会为c重新分配内存;这样即可保证内存有效利用;所以上面的(t)a(t)c比较的是a与c的引用,结果为True。这里面b由于进行了累加操作(b= b + lo;)b又重新分配了内存,所以(t)a(t)b比较的是引用,所以为False。
接下来我们再通过几个例子来理解下String(string)
String str1 = abc;
String str2 = str1;
str1 = 123;
Response.Write(str2);//abc
输出结果是abc,首先给str赋值为abc,接着执行str2=str1,使str2和str1指向同一引用,即内存地址。当执行str1 =123后,String对象是不可改变的,实质上str1=123是str1=newstring(123)的简写,它的每一次赋值都会抛掉原来的对象而生成一个新的字符串对象,分配新的内存空间,str1=123语句编译器私底下创建了一个新的字符串对象来保存新的字符序列123,也就是此str1已非彼str1了。因此str1的值的改变也就不能影响先前str1指向地址的值了,当然str2的值也就不会改变了。因此string是不可改变的。
通过上面的例子,如果我们执行下面这些语句:
String sql = “Select * From T_Test ”;
sql += “Where id=888 ”;
sql += “And type=3 ”;
sql += “Order By Desc”;
实际上这样是十分浪费内存空间的。如果是频繁的这样做的话,建议是使用StringBuilder对象,或者这样写:Stringsql= “Select * From T_Test” + “Where id=888 ” + “And type=3” +“OrderBy Desc ” ;
StringBuilder:
出于性能方面的考虑,大量的串联或所涉及其他字符串操作应通过StringBuilder类来执行。StringBuilder表示可变字符字符串,它允许我们有效的对字符串的字符执行动态操作,有效的缩减字符串的大小或者更改字符串中的字符。如果字符串变大,超过已经分配的字符的大小,StringBuilder就会自动的分配一个全新的、更大的数组,并开始使用新的数组,虽然StringBuilder对象是动态对象,允许扩充它所封装的字符串中字符的数量,但是您可以为它可容纳的最大字符数指定一个值。此值称为该对象的容量,不应将它与当前StringBuilder对象容纳的字符串长度混淆在一起。例如,可以创建 StringBuilder类的带有字符串“Hello”(长度为5)的一个新实例,同时可以指定该对象的最大容量为 25。当修改StringBuilder时,在达到容量之前,它不会为其自己重新分配空间。当达到容量时,将自动分配新的空间且容量翻倍。可以使用重载的构造函数之一来指定StringBuilder类的容量。
String 或 StringBuilder 对象的串联操作的性能取决于内存分配的发生频率。String串联操作每次都分配内存,而StringBuilder 串联操作仅当StringBuilder对象缓冲区太小而无法容纳新数据时才分配内存。因此,如果串联固定数量的 String 对象,则String类更适合串联操作。这种情况下,编译器甚至会将各个串联操作组合到一个操作中。如果串联任意数量的字符串,则StringBuilder对象更适合串联操作;例如,某个循环对用户输入的任意数量的字符串进行串联。