C# 字符串驻留机制
目录
一、具有相同字符序列的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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架