實例講解.NET字符串拘留池
本文將從.NET字符串拘留池講起,希望大家在今后碰到這樣的問題時,能正確處理。公共語言運行庫通過維護一個表來存放字符串,該表稱為拘留池,它包含程序中以編程方式聲明或創建的每個唯一的字符串的一個引用.因此,具有特定值的字符串的實例在系統中只有一個。
XiaoMing在博客園上發表的《年前的面試經歷(二) 》中回貼眾多,其中談到一個面試題:string a = "a" + "b"到底分配幾次內存。
這涉及到CLR內部的.NET字符串拘留池(string interning pool)問題。
網友 Ivony和 橫刀天笑的回貼引用資料指出拘留池是進程范圍內的,因此,有可能以下定義字串常量的代碼不會導致分配兩次內存——因為另一個進程可能已經在拘留池中創建了“a”或 “ab”這兩個字串對象。
- string s1 = "a";
- string s2 = "a";
- string s3 = "a" + "b";
- Console.WriteLine(s1);
- Console.WriteLine(s2);
- Console.WriteLine(s3);
我對此結論有點懷疑,于是到Google和MSDN中查找,發現.NET字符串拘留池的有關資料很混亂。***決定自己編程作實驗。
String類有一個IsInterned()方法用于檢測一個字串是否在拘留池中,另一個Intern()方法用于將一個字串加入拘留池中。
為此,我寫了以下測試代碼:
- class Program
- {
- //static string outerstr = "j";
- static void Main(string[] args)
- {
- string str = new string('j',1); //動態構建的字串,不會放到拘留池中
- if (string.IsInterned(str) == null)
- Console.WriteLine(str + " is not interned"); //不在拘留池
- else
- Console.WriteLine(str+ " is interned"); //在拘留池
- Console.ReadKey();
- string s = string.Intern(str); //強制加入拘留池
- //再次檢測
- if (string.IsInterned(str) == null)
- Console.WriteLine(str + "is not interned");
- else
- Console.WriteLine(str+ " is interned");
- Console.ReadKey();
- }
上述代碼運行結果如下:
- j is not interned
- j is interned
不管你運行多少次,也不管你是否同時運行多個此程序的實例,始終結果是一致的,都是上面的結果。這說明進程結束后,字串拘留池中的與此進程所裝載的程序集相關的字串常量對象被清除。
現在取消對outerstr 變量的注釋,結果變為:
- j is interned
- j is interned
這說明程序集中的常量“j”在裝載時被加入到了字串拘留池中,所以才有上述結果。
還有一個問題,字串拘留池中的對象能否跨越不同進程邊界共享?
編寫另一個測試程序:
- class Program
- {
- static void Main(string[] args)
- {
- string str = new string('j', 1);
- Console.WriteLine(string.IsInterned(str)==null);
- Console.ReadKey();
- }
- }
不管前一個測試程序是否在運行,上述代碼始終輸出true,說明“j”這個字串沒有在拘留池中,此進程無法獲取另一個進程追加到字串拘留池中的“j”字串。
從這些實驗是否可以得出以下結論?
當進程運行結束,此進程所加載的程序集中所定義的字串常量對象會被CLR從字串拘留池中移除。
因此,CLR字串拘留池中的字串常量是“進程和程序集相關”的。
應用程序所定義的字串常量對象在應用程序域裝載程序集時被加入到字串拘留池中。
所以,字串拘留池中的字串對象不能跨進程共享。不然,我們如何解釋代碼運行的結果?
由于同一進程中可以創建多個應用程序域,我還沒有編寫代碼測試字串拘留池中的字串對象是否可以在屬于同一進程的多個應用程序域共享。此問題留待進一步探索。
有無高人能徹底解釋清楚這一問題?
補充:
我的測試環境是Windows 7 + Visual Studio 2010 RC.
原文標題:探討一下.NET字串拘留池
鏈接:http://www.cnblogs.com/bitfan/archive/2010/03/02/1676733.html
【編輯推薦】