现在的位置: 首页 > 综合 > 正文

C# 字符串驻留机制

2013年03月21日 ⁄ 综合 ⁄ 共 3692字 ⁄ 字号 评论关闭

目录
一、具有相同字符序列的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 { getprivate 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 }

原文:通过内存分析工具来证明字符串驻留机制

抱歉!评论已关闭.