我不知道的C#—字符串池機制
對同一個字符串大量修改的問題可以使用StringBulid來解決這個問題,看看下面這個例子:
private string item = "string";
public void TestStringBuild()
{
long sbStart = DateTime.Now.Ticks;
UseStrigBuilder(1000);
long sbEnd = DateTime.Now.Ticks;
Console.WriteLine("使用StringBuilder消耗時間: "+(sbEnd-sbStart).ToString());
long strStart = DateTime.Now.Ticks;
UseString(1000);
long strEnd = DateTime.Now.Ticks;
Console.WriteLine("使用String消耗時間:"+(strEnd-strStart).ToString());
}
public string UseStrigBuilder(int number)
{
StringBuilder sb = new StringBuilder();
for(int i = 0; i < number; i++)
{
sb.Append(item);
}
sb.Remove(sb.Length-1 , 1);
return sb.ToString();
}
public string UseString(int number)
{
string result = "";
for(int i = 0; i < number; i++)
{
result += item;
}
return result;
}
輸出結果為
注:DateTime.Now.Ticks:此屬性的值表示自 0001 年 1 月 1 日午夜 12:00:00 以來已經過的時間的以 100 毫微秒為間隔的間隔數。
就是說這1000次循環如果使用StringBuilder的話節省了15625000毫秒的時間。
第二個問題,對多個引用賦值同一個字符串對象,CLR的解決方法更加巧妙。在默認情況下CLR會使用字符串池的機制,CLR啟動的時候,在內部創建一個容器,它以鍵值對的形式存在,鍵值是字符串對象內容,值是字符串在托管堆上的引用,當一個新的字符串對象創建的時候CLR檢查在這些值中是否已經存在這個字符串對象,如果已經存在就返回對應的值,也就是在托管堆中的引用,如果不存在就在這個容器中中開辟空間存放這個字符串,返回在他的引用。
這里還是用一段代碼來說明:
public void StringPoolTest()
{
string str1 = "789";
string str2 = "789";
Console.WriteLine(Object.ReferenceEquals(str1 , str2));
string str3 = "7" + "8" + "9";
Console.WriteLine(Object.ReferenceEquals(str1, str3));
char[] chars = new char[] { '7', '8', '9' };
string str4 = new string(chars);
Console.WriteLine(object.ReferenceEquals(str1 , str4));
}
輸出結果:
前兩次都輸出true說明str1和str2都指向同一個堆引用,最后一個輸出false是因為它使用new關鍵字進行內存分配,字符串池機制不起作用。
這里注意string str3 = "7" + "8" + "9";這個語句在正常的情況下只分配了一次內存,這個也是CLR的優化,在這里就沒有分配內存了,因為str1這里已經分配好了。
作者:Tyler Ning
出處:http://www.rzrgm.cn/tylerdonet/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,如有問題,請微信聯系冬天里的一把火
浙公網安備 33010602011771號