- 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代替。