C#里字符串驻留的几个小测试

 

在看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 Program
11     {
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 测试动态生成的string
21 
22             string s1 = s0 + "Test";//s2由两个字符串动态“相加”得到,由IL代码可知是调用 string String::Concat(string, string)方法后取返回值得到
23             Console.WriteLine("s1 is (test Concat): " + string.IsInterned(s1));
24 
25             #endregion
26 
27 
28             //下面这个测试说明了:如果const string 没有被访问,那么就不会被添加到字符串池里
29             #region 测试 const string
30 
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             #endregion
43 
44 
45             //下面这个测试说明了:static string 在类型任一个成员被访问之前就已经被添加到字符串池里了
46             #region 测试static string
47 
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             #endregion
55 
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             #endregion
70 
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             #endregion
83 
84             Console.ReadKey();
85         }
86 
87 
88         //方法里的字符串常量在编译时就会嵌入到代码里
89         //方法被调用之前只是以IL代码的形式存放在元数据里,没有被加载到内存里;当方法被调用时才会被加载到内存,方法里的所有文本字符串常量就全部添加到字符串池里
90         static string StrChange()
91         {
92             return "strChange";
93         }
94     }
95 
96 }

 

 

posted @ 2012-09-04 22:55  仙外仙  阅读(272)  评论(0编辑  收藏  举报