c#基础系列之System.String的深入理解

2020-01-05 09:21:48丽君

字符串地址= 0x80002d84

可见实例的值只分配了一次,但是有一点需要说明,字符串仅用于编译期能确定值的字符串,也就是常量字符串。如果我的程序修改为:


args = new string[] { "dfasfdsa"};
string s1 = "hello 大菜"+ args[0];
string s2 = "hello 大菜"+args[0];
unsafe
{
 fixed (char* p = s1)
 {
  Console.WriteLine("字符串地址= 0x{0:x}", (int)p);

 }
 fixed (char* p = s2)
 {
  Console.WriteLine("字符串地址= 0x{0:x}", (int)p);

 }
}

运行结果:

字符串地址= 0x2e3c
字符串地址= 0x2e7c

平时coding避免不了字符串的连接,如果一个频繁拼接字符串的场景下使用‘+',对程序整体性能和GC影响还是挺大的,为此c#推出了 StringBuilder类型来优化字符串的拼接。相对于String类型的不变性来说,StringBuilder更像是可变的字符串类型。它的底层数据结构是一个Char的数组。另外还有容量(默认为16),最大容量(默认为int.MaxValue)等属性。StringBuilder的优势在于字符总数未超过‘容量'的时候,底层数组不会重新分配,这和String每次都重新分配形成最大的对比。如果字符总数超过‘容量',StringBuilder会自动倍增容量属性,用一个新的数组来容纳原来的值,原来数组将会被GC回收。可见如果StringBuilder频繁的动态扩容也会损害性能,但是影响可能会比String小的多。 合理的设置StringBuilder初始容量对程序有很大帮助。测试如下:


int count = 100000;
Stopwatch sw = new Stopwatch();
sw.Start();
string s = "";
for (int i = 0; i < count; i++)
 {
  s += i.ToString();
 }
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

运行结果: