小新的技术天地

Make It Works !

博客园 首页 新随笔 联系 订阅 管理

String s1 = “Hello”;
String s2 = “Hel”;
String s3 = s2 + “lo”;
Console.WriteLine(Object.ReferenceEquals(s1,s3));
Console.WriteLine(s1.Equals(s3));

这里,s2引用的字符串(“Hel”)根一个文本常量字符串(“lo”)被连接在一起。结果构造了一个新的字符串 ,并且被s3引用。这个动态创建的字符串“Hello”没有被加到散列表中,自然Console.WriteLine(Object.ReferenceEquals(s1,s3))返回false。s1.Equals(s3)返回true,因为两个字符创串实际上仍便是着同样的字符集。(如果将s3 =“Hel“+ “lo“,则Object.ReferenceEquals(s1,s3)返回true)。显然ReferenceEquals效率较高。有没有办法使含有相同字符集的动态字符串变为托管堆中的一个对象呢,其实是有的,那就是 String类型提供的:
public static String Intern(String str);
public static String IsIntern(String str);

第一方法,接受一个String参数 ,然后在散列表中查找它。如果能找到,Intern返回已经存在的String对象的引用,找不到的话,将该字符串添加到散列表中,返回它的引用。并且,如果程序不在保存有原来String对象的引用,这个String对象就会被回收。

 我们重写上面的代码:
            String s1 = "Hello";
            String s2 = "Hel";
            String s3 = s2 + "lo";
            s3 = String.Intern(s3);
            Console.WriteLine(Object.ReferenceEquals(s1,s3));
            Console.WriteLine(s1.Equals(s3));
这样,就返回两个true了,执行效率也高了,s3原来引用的对象会被垃圾回收。不过实际上要比前面的代码要慢一点,因为String的Intern方法所做的工作。所以,只有当我们需要在同一程序中多次比较同一个字符串时,才使用字符串驻留技术。不然性能是损伤而不是提高。

另外一个IsInterned方法,节本上跟Intern完成同样的功能,区别在于如果散列表中不含该字符串,IsInterned返回null,而不是添加这个字符串到散列表中。
实际上C#便一起就使用IsInterned方法对switch/case语句进行性能优化。有兴趣的朋友请参见《.NET框架程序设计(修订版)》264页的详细分析。

注:此文参考《.NET框架程序设计(修订版)》

posted on 2004-10-27 12:22  小新0574  阅读(1421)  评论(0编辑  收藏  举报