string与StringBuilder
今天无意间看到C#6.0的新特性$”“的用法发现很神奇,就查看了很多资料,正好就对string型做一个整理
string是什么
说string之前,首先先介绍下Char。Char在.Net中表示字符,即一个16位的Unicode代码值,它是一个值类型并且长度固定。而string被称为字符串,可以理解成多个字符的集合,它是特殊的引用类型。它继承自System.Object肯定是个引用类型,但是在应用表现上又凸现出值类型的特点,因为string不能改变自身的值,如果用string的话,函数调用之后string的值不会发生改变,代码中改变它的值实际上是新实例化了一个string变量。
Console.Write("a" +"b"); //输出ab
Console.Write('a'+'b'); //输出195其中'a'=97,'b'=98
Console.Write(string.Concat('a' ,'b')); //输出ab
虽然string是引用类型,但是我们不关心string变量的地址,只关心它的值,如果多个string对象引用同一个地址,当其中的某个对象改变时,使得此改变不会影响到其他对象。然而如果每次都实例化同一个值的string变量,会造成内存浪费,因此CLR默默地维护了一个叫做驻留池(Intern Pool)的表。这个表记录了所有在代码中使用字面量声明的字符串实例的引用。CLR在为i.ToString()方法的返回值分配内存时,并不会到驻留池中去检查是否有值为“1”的字符串已经存在了,所以自然不会让s2指向驻留池内的对象。为了让编程者能够强制CLR检查驻留池,以避免冗余的字符串副本,String类的设计者提供了一个名为Intern的类方法。
可以使用ReferenceEquals查看是否是同一个引用。注意:ReferenceEquals只能用于引用类型的比较,值类型一律返回FALSE。
int i = 1;
string s1 = "12";
string s2 = "1";
string s3 = "1" + "2"; //s1,s3是同一个引用
string s4 = s2 + "2"; //s3,s4不是同一个引用
string s5 = string.Concat("1", "2"); //s3,s4,s5都不是同一个引用
string s6 = i.ToString();
string s7 = new string(s2.ToArray()); //s2,s6,s7都不是同一个引用
string s8 = string.Intern(s5); //s1,s3,s8是同一个引用
字符串格式化
字符串格式化有两种方法一种是string.Format(),还有一种是$”“的方式,具体以下面这个例子来说明。
int a = 1,b=2,c=3;
string s1 = string.Format("Hello {0}{1}{2}", a, b, c);
string s2 = $"Hello {a}{b}{c}"; //s1与s2值相等,不是同一个引用
上面举的字符串拼接的例子,实际上拼接得到的是一个新的字符串,而原有的字符串和仍然存在,这在对字符串进行大量修改的场合,会导致严重的资源浪费。
而C#中采用StringBuilder解决这个问题。对StringBuilder的操作,如拼接Append(),插入Insert(),删除Remove(),替换Replace(),都是对现有的字符串进行操作,而不会引入新的字符串,避免了新建string类所造成的系统开销。
StringBuilder的用法
StringBuilder对象在做字符串连接操作时是在原来的字符串上进行修改,改善了性能。这一点我们平时使用中也许都知道,连接操作频繁的时候建议使用StringBuilder对象。但同时,在任何地方都使用StringBuilder是不恰当的做法。
从逻辑上说,StringBuilder对象包含一个字段,该字段引用了有Char结构构成的一个数组。可利用StringBuilder的各个成员来操作这个字符数组,高效率的缩短或更改字符串中的字符。如果字符串变大,超过已分配的字符数组的大小,StringBuilder会自动分配一个新的、更大的数组,复制字符,并开始使用新数组。前一个数组会被垃圾回收。
修改字符串
Append 方法可用来将文本或对象的字符串表示形式添加到由当前 StringBuilder 对象表示的字符串的结尾处。下面的示例将一个 StringBuilder 对象初始化为“Hello World”,然后将一些文本追加到该对象的结尾处。将根据需要自动分配空间。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Append(" What a beautiful day.");
Console.WriteLine(MyStringBuilder); //输出Hello World! What a beautiful day.
Insert 方法将字符串或对象添加到当前 StringBuilder 中的指定位置。下面的示例使用此方法将一个单词插入到 StringBuilder 的第六个位置。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Insert(6,"Beautiful ");
Console.WriteLine(MyStringBuilder); //输出Hello Beautiful World!
可以使用 Remove 方法从当前 StringBuilder 中移除指定数量的字符,移除过程从指定的从零开始的索引处开始。下面的示例使用 Remove 方法缩短 StringBuilder。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Remove(5,7); //第5个位置,长度为7
Console.WriteLine(MyStringBuilder); //输出Hello
Replace使用 Replace 方法,可以用另一个指定的字符来替换 StringBuilder 对象内的字符。下面的示例使用 Replace 方法来搜索 StringBuilder 对象,查找所有的感叹号字符 (!),并用问号字符 (?) 来替换它们。
StringBuilder MyStringBuilder = new StringBuilder("Hello World!");
MyStringBuilder.Replace('!', '?');
Console.WriteLine(MyStringBuilder); //输出Hello World?
将Stringbuilder串转换为string形式,通过ToSting方法,会创建新的string对象。