62. System.String 和System.StringBuilder有什么区别?

String   对象是不可改变的。每次使用   System.String   类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的   String   对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用   System.Text.StringBuilder   类。例如,当在一个循环中将许多字符串连接在一起时,使用   StringBuilder   类可以提升性能。

StringBuilder类并没有String类的功能强大,只提供基本的替换和添加和删除字符串中的文本,但它的工作效率非常高,当定义StringBuilder对象时可以指定内存的内存容量,如果不指定系统就会根据对象初始化时的字符串长度来确定。它有两个主要参数Length和Capacity分别表示字符串的实际长度和字符串占据的内存空间长度。对字符串的修改就是在这个内存中进行的,大大提高了添加和替换的的效率。 
如定义:

StringBuilder sb=new StringBuilder("Hello,Welcome",100);//初始化对象并设置初始容量为100
sb.Append(" to www.csdn.net");
sb.Replace(old,new);//将old替换为new,作用与String.Replace()一样只是不需要在过程中复制字符。
StringBuilder的成员:
StringBuilder sb=new StringBuilder("错误!超链接引用无效。定义初值为www.csdn.net的对象。
StringBuilder sb=new StringBuilder(20);初始化容量为20的空对象。
另外StringBuilder还有MaxCapacity属性用来限定对象可以使用的最大容量。默认大约是int.MaxValue(20亿)
可以在使用过程中定义sb.MaxCapacity=value;
sb.Append(),给当前字符串追加字符串。
sb.AppendFormat()——添加特定格式的字符串
sb.Insert()——插入一个子字符串
sb.Remove()——从当前字符串删除字符
sb.Replace()——替换字符串中指定的字符
sb.ToString()——将sb转化为String 对象 

StringBuilder sb=new StringBuilder("Hello,Welcome",100);//初始化对象并设置初始容量为100
sb.Append(" to www.csdn.net");
sb.Replace(old,new);//将old替换为new,作用与String.Replace()一样只是不需要在过程中复制字符。
StringBuilder的成员:
StringBuilder sb=new StringBuilder("错误!超链接引用无效。定义初值为www.csdn.net的对象。
StringBuilder sb=new StringBuilder(20);初始化容量为20的空对象。另外StringBuilder还有MaxCapacity属性用来限定对象可以使用的最大容量。默认大约是int.MaxValue(20亿)可以在使用过程中定义sb.MaxCapacity=value;sb.Append(),给当前字符串追加字符串。
sb.AppendFormat()——添加特定格式的字符串
sb.Insert()——插入一个子字符串
sb.Remove()——从当前字符串删除字符
sb.Replace()——替换字符串中指定的字符
sb.ToString()——将sb转化为String 对象 

  1. string

      字符串驻留池(StringPooling):公共语言运行库通过维护一个哈希表来存放字符串,该表称为字符串驻留池。它包含程序中以编程方式声明或创建的每个唯一的字符串的一个引用。因此,具有特定值的字符串的实例在系统中只有一个。 [应该是应用了单例模式的应用。 

      字符串驻留:根据字符串驻留池的定义可以看出字符串驻留技术的用处。主要目的是减少内存开销和系统开销,充分利用资源。提供了两个重要的方法:


        1:String.Intern :检索系统对指定 String 的引用。如果 str 的值已经留用,则返回系统的引用;否则返回对带有 str 值的字符串的新引用。
        2:String.IsInterned 方法 :检索对指定String 的引用。如果 str 位于公共语言运行库“拘留池”中,则为对它的 String 引用;否则为 nullNothingnullptrnull 引用

      字符串的不可更改特性:当一个字符串创建后,我们就不能对它进行增加长,或者是缩减,也不能修改其中的任何字符。但有朋友可以会问,那为什么能对字符串进行那么多的操作呢?例如:"+"操作符,Substring等等。其实这些操作都会产生一个全新的字符串,而不是在原来字符串在修改。只要是把操作后的数据赋值给一个新的字符串变量,那么就是产生一个和原字符串完全不同的对象。先看下赋值的情况:把一个变量直接赋值给一个新的字符串变量,根据上面的理论来看,下面应该会返回false,但实际结果返回的是true,因为在字符串驻留的存在。 

            string b = "aaa";
            string c = b;         
            Console.WriteLine(Object.ReferenceEquals(b, c));

 

     但是这并不代表b和c是一样的,我们再看下如下代码:分别分返回aaa,aaaa,false,既然string属于引用类型,但为什么修改c的值后,b的值没有跟着变呢,这只因为把字符串赋值给另一个字符串时,会创建一个全新的String对象。

            string b = "aaa";
            string c = b;
            c = b + "a";
            Console.WriteLine(b);
            Console.WriteLine(c);
            Console.WriteLine(Object.ReferenceEquals(b, c));

 

      字符串中的"+"操作符:通常我们会对字符串进行修改,例如"+"号,表示连接多个字符串。但加号会产生非常多的字符串,这样会造成非常多的内存开销和系统开销,这里可以利用StringBuilder来解决多字符串连接的性能问题。来看下下面的示例代码:

            string b = "aaa";
            b = b + "a";
            StringBuilder strb = new StringBuilder();
            strb.Append("aaa");
            strb.Append("a");

 

      IL代码:由于ConCat操作后会生成全新的对象,而StringBuilder是在原对象上修改变量,并不会生成新对象,这样就会产生性能优势。上面的代码只是示范,一般在大量字符串拼接时这种性能问题会倍增。

安全字符串:如果字符串中存放了此比较敏感的信息,例如用户的密码,信用卡信息之类的,如果此时有非安全代码或者是非托管代码访问这些字符串,这些代码可以扫描进程的地址空间,访问包含敏感数据的字符串,以一种非授权的方式来使用这些数据。即使只使用这些字符串时间很短,马上回进行垃圾回收,也是需要一定时间的,而且string本身无法修改的特性,使这些非安全的或者是非托管代码在访问时会留string的副本在内存中。

      FCL解决了这个问题,它就是System.Security.SecureString:表示应保密的文本。文本在使用时出于保密目的被加密,并在不再需要时从计算机内存中删除。无法继承此类。当你构造一个SecureString对象时,系统会在内存中分配一个非托管区域,里面包含一个字符数组,里面的内容均是经常加密的。之所以是非托管空间,就是为了不让垃圾回收器来管理。

      System.Security.SecureString实现了IDisposable接口,这样可以保证在使用完后立即对字符串进行销毁。


作者:古梅飞动
公司:蜜团科技
出处:http://www.mitsofts.com/index.php
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/luhuan860/p/1750054.html