C#中的string

      这篇文章我来总结一些string相关知识。html

      System.String类型:平时在编程中对于string的用法应该是特别频繁的。一般咱们会把string,int ,float放在一块儿比较,因为后面两个都是值类型,因此很是想固然的会认为string也会是值类型,这是错误的,string因为自身特殊的缘由,它最终属于引用类型,固然它的最终基类仍是Object。字符串存放在托管堆上,并不存放在堆栈中。
 
      构造字符串:如何来构造一个字符串呢?编程

         第一:既然string属于引用类型,那么是否能够用new操做符来生成呢?下面的代码是错误的。
   数组

String c  =   new  String( " aaa " );

  

        第二:咱们一般的作法是不用new,而是直接赋值。安全

string  a  =   " aaaa " ;

  
         生成的部分IL代码:在生成的IL代码中并无出现newobj操做符,但出现了ldstr:推送对元数据中存储的字符串的新对象引用。ide

     

IL_0001:  ldstr       " aaaa "
IL_0006:  stloc.
0

  

      字符串驻留池(String Pooling):公共语言运行库经过维护一个哈希表来存放字符串,该表称为字符串驻留池。它包含程序中以编程方式声明或建立的每一个惟一的字符串的一个引用。所以,具备特定值的字符串的实例在系统中只有一个。 [应该是应用了单例模式的应用。单例能够参考:老生常谈:单件模式],这里很是谢谢飞林沙的提示,应该是享元模式,一样能够参考以下文章:老生常谈:享元模式性能

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


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

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

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

   

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

             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操做后会生成全新的对象,而StringBuild是在原对象上修改变量,并不会生成新对象,这样就会产生性能优点。上面的代码只是示范,通常在大量字符串拼接时这种性能问题会倍增。

复制代码
.method  private  hidebysig  static   void   Main( string [] args) cil managed
{
  .entrypoint
  
//  代码大小       50 (0x32)
  .maxstack   2
  .locals init ([
0 string  b,
           [
1 class  [mscorlib]System.Text.StringBuilder strb)
  IL_0000:  nop
  IL_0001:  ldstr      
" aaa "
  IL_0006:  stloc.
0
  IL_0007:  ldloc.
0
  IL_0008:  ldstr      
" a "
  IL_000d:  call       
string  [mscorlib]System.String::Concat( string ,
                                                              
string )
  IL_0012:  stloc.
0
  IL_0013:  newobj     instance 
void  [mscorlib]System.Text.StringBuilder::.ctor()
  IL_0018:  stloc.
1
  IL_0019:  ldloc.
1
  IL_001a:  ldstr      
" aaa "
  IL_001f:  callvirt   instance 
class  [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append( string )
  IL_0024:  pop
  IL_0025:  ldloc.
1
  IL_0026:  ldstr      
" a "
  IL_002b:  callvirt   instance 
class  [mscorlib]System.Text.StringBuilder [mscorlib]System.Text.StringBuilder::Append( string )
  IL_0030:  pop
  IL_0031:  ret
//  end of method Program::Main
复制代码

   

      安全字符串:若是字符串中存放了此比较敏感的信息,例如用户的密码,信用卡信息之类的,若是此时有非安全代码或者是非托管代码访问这些字符串,这些代码能够扫描进程的地址空间,访问包含敏感数据的字符串,以一种非受权的方式来使用这些数据。即便只使用这些字符串时间很短,立刻回进行垃圾回收,也是须要必定时间的,并且string自己没法修改的特性,使这些非安全的或者是非托管代码在访问时会留string的副本在内存中。

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

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

相关文章
相关标签/搜索