在看anytao的《你必須知道的.NET》 http://www.cnblogs.com/anytao/archive/2008/08/27/must_net_22.html,看到字串駐留這部分時,對於裡面提到的幾個問題有些小疑問,特別是後面幾個問題,沒看懂,所以特地做了些小測試,也不知是否正確,或者說那裡表達得有問題,請瞭解這方面的大俠們多指點。
該說的在代碼裡已經說,其他的就不廢話了
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace Test 7 { 8 9 10 class Program11 {12 const string strConst = "strConst";//編譯時間確定,存放在中繼資料裡,被訪問之前不會被載入到記憶體13 readonly static string strStatic = "strStatic";//運行時確定14 15 static void Main(string[] args)16 {17 string s0 = "str";18 19 //下面這個測試說明了:兩個字串動態“相加”後得到的字串是在運行時去確定的,不會添加到字串池裡20 #region 測試動態產生的string21 22 string s1 = s0 + "Test";//s2由兩個字串動態“相加”得到,由IL代碼可知是調用 string String::Concat(string, string)方法後取傳回值得到23 Console.WriteLine("s1 is (test Concat): " + string.IsInterned(s1));24 25 #endregion26 27 28 //下面這個測試說明了:如果const string 沒有被訪問,那麼就不會被添加到字串池裡29 #region 測試 const string30 31 //執行下面這句代碼時,編譯器會直接把字串 "strConst" 嵌入到代碼來替代 常量strConst,32 //這樣子就會導致將字串 "strConst" 加入到字串池裡(如果字串池沒有這個項)。所以這樣子測試是不準確的33 // Console.WriteLine(string.IsInterned(strConst));34 35 //const string 在編譯時間嵌入到代碼替換對應的那個常量;當const string 所在的方法被調用時,該const string就被添加到字串池裡36 37 string s2 = s0 + "Const";38 Console.WriteLine("s2 is (test const string): " + string.IsInterned(s2));39 //Console.WriteLine(strConst);40 //Console.WriteLine("s4 is: " + string.IsInterned(s4));41 42 #endregion43 44 45 //下面這個測試說明了:static string 在類型任一個成員被訪問之前就已經被添加到字串池裡了46 #region 測試static string47 48 //static string,在這個類型的任何一個成員被訪問之前,CLR會調動類型的類型構造器,也就是靜態構造器(可顯式定義,但只能有一個,必須無參)49 //類型構造器先調用static成員的初始化代碼,再調用自己顯式添加的代碼。所以static string初始化時賦予的字串會被添加到字串池50 51 string s3 = s0 + "Static";52 Console.WriteLine("s3 is (test static string): " + string.IsInterned(s3));53 54 #endregion55 56 57 //下面這個測試說明了:字串不在乎聲明得前面還是後面,因為字串常量是在編譯時間確定的,58 //反正在方法被訪問時,方法就被載入到記憶體,裡面所有的字串常量一次性全部添加到字串池裡59 #region 測試先輸出後定義60 61 // string s7 = strConst;//在編譯的時候直接用常量strConst的內容 "strConst" 內嵌程式碼替代 s7;從而添加進了字串池62 63 string s4 = s0 + "before define";64 Console.WriteLine("s4 is (test before define): " + string.IsInterned(s4));65 66 //在編譯的時候就已經把 "strbefore define" 放到字串池裡了。如果是放在其他函數裡,為什麼不也在編譯的時候就放到字串池裡?67 string s40 = "strbefore define";68 69 #endregion70 71 72 //下面這個測試說明了:方法被調用前,裡面所有的東西都只是在中繼資料裡,沒有被載入到記憶體;73 //當某方法被調用時才會被載入到記憶體,方法的所有文本字串一次性添加到字串池裡74 #region 調用方法75 76 string s5 = s0 + "Change";77 Console.WriteLine("s5 is (before mothed): " + string.IsInterned(s5));//調用方法前,"strChange" 沒有被添加到字串池裡78 StrChange();79 Console.WriteLine("s5 is (after mothed) : " + string.IsInterned(s5));//調用方法後,"strChange" 已經被添加到字串池裡了 80 81 82 #endregion83 84 Console.ReadKey();85 }86 87 88 //方法裡的字串常量在編譯時間就會嵌入到代碼裡89 //方法被調用之前只是以IL代碼的形式存放在中繼資料裡,沒有被載入到記憶體裡;當方法被調用時才會被載入到記憶體,方法裡的所有文本字串常量就全部添加到字串池裡90 static string StrChange()91 {92 return "strChange";93 }94 }95 96 }