- String类型不可变。定义string变量时会在堆上分配存储空间,而对该变量进行值变更时会重新分配一个存储空间,且保留原存储空间。
测试思路:获取string类型变量值变更前后的存储空间地址,判断地址是否相同。
获取引用类型地址代码:
public static string GetMemory(Object o) { GCHandle h = GCHandle.Alloc(o, GCHandleType.Pinned); IntPtr addr = h.AddrOfPinnedObject(); return "0x" + addr.ToString("X"); }
测试代码:
string str= "hello"; Console.WriteLine(GetMemory(str)); str = "hi"; Console.WriteLine(GetMemory(str));
测试结果:
测试表明:string类型变量赋值完成后一旦修改值,实际上是重新分配一存储空间存储修改的值,原来的存储空间保留并保存原值。也就证明所谓的“string类型值不可变”。
- string字符串拼接性能测试。通过循环模拟实现字符串拼接,并将所运行时间与stringbuilder实现相同功能所需时间对比。
public static void StringConcat(int num) { string str = ""; for(int i = 0; i < num; i++) { str += i.ToString(); } } public static void StringBuilderTest(int num) { StringBuilder builder = new StringBuilder(); for(int i = 0; i < num; i++) { builder.Append(i.ToString()); } string str = builder.ToString(); }
测试代码:
int num = 1000; do { int start = Environment.TickCount; /******使用字符串连接构建字符串******/ StringConcat(num); int middle = Environment.TickCount; /******使用StringBuilder构建字符串******/ StringBuilderTest(num); int end = Environment.TickCount; int t1 = middle - start; int t2 = end - middle; Console.WriteLine("循环次数:{0},StringBuilder:{1}ms,字符串拼接:{2}ms", num, t2, t1); num = (int)(num * 1.5); } while (num < 1000000);
测试结果:
结果表明:大量字符串连接性能很差,这当然是由string类型值不可变特性确定的,解决方案是采用stringbuilder代替。