当前位置导航:炫浪网>>网络学院>>网页制作>>ASP.NET教程

在ASP.NET中显示Linq To SQL输出的SQL语句

  昨天调试一段程序发现内存始终释放不掉,最后终于发现是对String 的错误使用造成,这促使我今天又仔细研究了一下String类型,不研究不知道,一研究发现我过去对String 的很多认识都是错误的,感觉这种错误认识还比较有典型性,于是写下此文和大家一起探讨。

  1. String 类型变量追加,或修改后的新String对象是驻留(Interned)的。

  如下面代码

  string s1 = "abcd";

  string s2 = s1 + "e";

  我过去想当然的认为s2 是驻留的,但实际上并非如此,用 string.IsInterned 方法检测s2是非驻留的。后来研究发现只有常量字符串才会默认驻留,其他的字符串变量哪怕是采用 new string 构造出来的,默认都非驻留,除非用string.Intern 强行驻留。后面我将提到驻留对内存的影响,微软之所以不让所有的字符串都驻留,我认为还是处于内存方面的考虑。

  2. String 变量不再引用后CLR会通过GC自动释放其内存。

  string s1 = "abcd";

  s1 = null;

  上面代码,我想当然的认为s1 = null 后已经不再对 "abcd" 这个字符串引用,如果没有其他引用指向这个字符串,GC会释放"abcd"这块内存。实际结果却是否定的。因为s1 被赋予了一个常量,导致 "abcd"这个字符串是驻留的,驻留的字符串在进程结束之前无法被自动释放。更糟糕的是,我昨天调试的那段程序里面大量的字符串变量被采用 string.Intern 强制驻留,这导致我把所有的托管对象都释放了依然无法释放那部分大概30多M的内存。

  遗憾的是微软的MSDN中文版中string.Intern 的帮助信息里面竟然漏掉了性能考谅(Performance consideration) 这一节,我估计大多数中国程序员包括我在内如果有中文的帮助是懒得去看英文的。很遗憾微软中文的帮助不知道为什么把最重要的部分给漏了。下面是英文帮助中Performance consideration 一节。

  Performance Considerations

  If you are trying to reduce the total amount of memory your application allocates, keep in mind that interning a string has two unwanted side effects. First, the memory allocated for interned String objects is not likely be released until the common language runtime (CLR) terminates. The reason is that the CLR's reference to the interned String object can persist after your application, or even your application domain, terminates. Second, to intern a string, you must first create the string. The memory used by the String object must still be allocated, even though the memory will eventually be garbage collected.

  The .NET Framework version 2.0 introduces the CompilationRelaxations..::.NoStringInterning enumeration member. The NoStringInterning member marks an assembly as not requiring string-literal interning. You can apply NoStringInterning to an assembly using the CompilationRelaxationsAttribute attribute. Also, when you use the Native Image Generator (Ngen.exe) to compile an assembly in advance of run time, strings are not interned across modules.

  看了英文的帮助就知道Intern 后的字符串是无法释放的了。

  3. 两个String如果引用不同只能用Equal 比较。

  我一直想当然的认为 两个String 类型如果用 == 操作符比较,将比较其引用。所以如果两个String引用不同,则只能使用Equal 来比较它们是否相等。

  比如下面语句

  string s2 = new StringBuilder().Append("My").Append("Test").ToString();

  string s3 = new StringBuilder().Append("My").Append("Test").ToString();

  如下方法比较其引用

  Console.WriteLine((object)s3 == (object)s2);

  得到结果为 false,即s2, s3指向不同引用。

  那么我想当然的认为 Console.WriteLine(s3 == s2); 的结果也是false,因为string 是引用类型,用==操作符比较引用类型变量,如果两个变量的引用不同,即便值相同,也会返回false. 然而运行的结果让我大跌眼镜。返回的值是true.

相关内容
赞助商链接