目录
一、具有相同字符序列的String对象不会重复创建
二、字符串驻留机制同样于string literal + string literal的运算
三、字符串驻留机智不适合variable + string literal形式
四、调用string.Intern可以对运算结果进行强制驻留
五、驻留的字符串不能被GC回收
六、字符串驻留是基于整个进程的
1
public
class
StringInMemory
2 {
3 /// <summary>
4 /// 1. 具有相同字符序列的String对象不会重复创建
5 /// </summary>
6 public static void BuildString()
7 {
8 var str1 = " ABCDEFG " ;
9 var str2 = " ABCDEFG " ;
10 var str3 = " 1234567 " ;
11 var str4 = " 1234567 " ;
12
13 GC.Collect();
14 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str1, str2));
15 }
16
17 /// <summary>
18 /// 2. 字符串驻留机制同样于string literal + string literal的运算
19 /// </summary>
20 public static void BuildString2()
21 {
22 var str1 = " ABCDEFG " ;
23 var str2 = " ABCD " + " EFG " ;
24 var str3 = " 1234567 " ;
25 var str4 = " 1234 " + " 567 " ;
26
27 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str1, str2));
28 }
29
30 /// <summary>
31 /// 3. 字符串驻留机智不适合Variable + string literal形式
32 /// </summary>
33 public static void BuildString3()
34 {
35 /// 无论是变量和一个字符串常量相加,还是两个字符串常量相加,运算的结果“ABCDEFG1234678”
36 /// 并没有被驻留下来(实际上此时它已经是一个垃圾对象,GC可以对其进行回收)。
37 var str1 = " ABCDEFG " ;
38 var str2 = " 1234567 " ;
39 var str3 = " ABCDEFG " + str2;
40 var str4 = str1 + " 1234567 " ;
41 var str5 = str1 + str2;
42
43 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str3, str4));
44 }
45
46 /// <summary>
47 /// 4. 调用string.Intern可以对运算结果进行强制驻留
48 /// </summary>
49 public static void BuildString4()
50 {
51 /// 虽然涉及到变量的字符串连接运算结果不会被驻留,但是我们可以通过调用string.Intern方法对其进行强制驻留,
52 /// 该方法会迫使传入传入参数表示的字符串被保存到驻留池中
53 var str1 = " ABCDEFG " ;
54 var str2 = " 1234567 " ;
55 var str3 = string .Intern( " ABCDEFG " + str2);
56 var str4 = string .Intern(str1 + " 1234567 " );
57
58 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str3, str4));
59 }
60
61 /// <summary>
62 /// 5. 驻留的字符串不能被GC回收
63 /// </summary>
64 public static void BuildString5()
65 {
66 BuildString();
67
68 GC.Collect();
69 GC.Collect();
70 }
71
72 /// <summary>
73 /// 6. 驻留的字符串是基于整个进程范围的,而不是基于当前AppDomain。
74 /// </summary>
75 public static void BuildString6()
76 {
77 AppDomainContext.CreateDomainContext( " Domain A " ).Invoke < Foo > (foo => foo.BuildString());
78 AppDomainContext.CreateDomainContext( " Domain B " ).Invoke < Foo > (foo => foo.BuildString());
79 AppDomainContext.CreateDomainContext( " Domain C " ).Invoke < Foo > (foo => foo.BuildString());
80 }
81
82 public class AppDomainContext
83 {
84 public AppDomain AppDomain { get ; private set ; }
85 private AppDomainContext( string friendlyName)
86 {
87 this .AppDomain = AppDomain.CreateDomain(friendlyName);
88 }
89
90 public static AppDomainContext CreateDomainContext( string friendlyName)
91 {
92 return new AppDomainContext(friendlyName);
93 }
94
95 public void Invoke < T > (Action < T > action)
96 {
97 T instance = (T) this .AppDomain.CreateInstanceAndUnwrap( typeof (T).Assembly.FullName, typeof (T).FullName);
98 action(instance);
99 }
100 }
101
102 public class Foo : MarshalByRefObject
103 {
104 public void BuildString()
105 {
106 var str1 = " ABCDEFG " ;
107 var str2 = " ABCDEFG " ;
108 var str3 = " 1234567 " ;
109 var str4 = " 1234567 " ;
110 }
111 }
112 }
2 {
3 /// <summary>
4 /// 1. 具有相同字符序列的String对象不会重复创建
5 /// </summary>
6 public static void BuildString()
7 {
8 var str1 = " ABCDEFG " ;
9 var str2 = " ABCDEFG " ;
10 var str3 = " 1234567 " ;
11 var str4 = " 1234567 " ;
12
13 GC.Collect();
14 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str1, str2));
15 }
16
17 /// <summary>
18 /// 2. 字符串驻留机制同样于string literal + string literal的运算
19 /// </summary>
20 public static void BuildString2()
21 {
22 var str1 = " ABCDEFG " ;
23 var str2 = " ABCD " + " EFG " ;
24 var str3 = " 1234567 " ;
25 var str4 = " 1234 " + " 567 " ;
26
27 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str1, str2));
28 }
29
30 /// <summary>
31 /// 3. 字符串驻留机智不适合Variable + string literal形式
32 /// </summary>
33 public static void BuildString3()
34 {
35 /// 无论是变量和一个字符串常量相加,还是两个字符串常量相加,运算的结果“ABCDEFG1234678”
36 /// 并没有被驻留下来(实际上此时它已经是一个垃圾对象,GC可以对其进行回收)。
37 var str1 = " ABCDEFG " ;
38 var str2 = " 1234567 " ;
39 var str3 = " ABCDEFG " + str2;
40 var str4 = str1 + " 1234567 " ;
41 var str5 = str1 + str2;
42
43 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str3, str4));
44 }
45
46 /// <summary>
47 /// 4. 调用string.Intern可以对运算结果进行强制驻留
48 /// </summary>
49 public static void BuildString4()
50 {
51 /// 虽然涉及到变量的字符串连接运算结果不会被驻留,但是我们可以通过调用string.Intern方法对其进行强制驻留,
52 /// 该方法会迫使传入传入参数表示的字符串被保存到驻留池中
53 var str1 = " ABCDEFG " ;
54 var str2 = " 1234567 " ;
55 var str3 = string .Intern( " ABCDEFG " + str2);
56 var str4 = string .Intern(str1 + " 1234567 " );
57
58 System.Diagnostics.Debug.Assert( string .ReferenceEquals(str3, str4));
59 }
60
61 /// <summary>
62 /// 5. 驻留的字符串不能被GC回收
63 /// </summary>
64 public static void BuildString5()
65 {
66 BuildString();
67
68 GC.Collect();
69 GC.Collect();
70 }
71
72 /// <summary>
73 /// 6. 驻留的字符串是基于整个进程范围的,而不是基于当前AppDomain。
74 /// </summary>
75 public static void BuildString6()
76 {
77 AppDomainContext.CreateDomainContext( " Domain A " ).Invoke < Foo > (foo => foo.BuildString());
78 AppDomainContext.CreateDomainContext( " Domain B " ).Invoke < Foo > (foo => foo.BuildString());
79 AppDomainContext.CreateDomainContext( " Domain C " ).Invoke < Foo > (foo => foo.BuildString());
80 }
81
82 public class AppDomainContext
83 {
84 public AppDomain AppDomain { get ; private set ; }
85 private AppDomainContext( string friendlyName)
86 {
87 this .AppDomain = AppDomain.CreateDomain(friendlyName);
88 }
89
90 public static AppDomainContext CreateDomainContext( string friendlyName)
91 {
92 return new AppDomainContext(friendlyName);
93 }
94
95 public void Invoke < T > (Action < T > action)
96 {
97 T instance = (T) this .AppDomain.CreateInstanceAndUnwrap( typeof (T).Assembly.FullName, typeof (T).FullName);
98 action(instance);
99 }
100 }
101
102 public class Foo : MarshalByRefObject
103 {
104 public void BuildString()
105 {
106 var str1 = " ABCDEFG " ;
107 var str2 = " ABCDEFG " ;
108 var str3 = " 1234567 " ;
109 var str4 = " 1234567 " ;
110 }
111 }
112 }