字符、字符串和文本的处理之String类型

.Net Framework中处理字符和字符串的主要有如下这么几个类:html

(1)、System.Char类 一基础字符串处理类正则表达式

(2)、System.String类 一处理不可变的字符串(一经建立,字符串便不能以任何方式修改)编程

(3)、System.Text.StringBuilder类 一更高效地构建字符串数组

(4)、System.Secureity.SecureString类 一对字符串进行保护操做,它能够保护密码和信用卡资料等敏感字符串.安全

 

1、String类型编程语言

一、简介布局

在任何应用程序里面,String类型都是用的最多的类型之一.一个String表明一个不可变的(immutable)的顺序字符串,String类型直接派生自Object,因此它是引用类型.因此String对象(它的字符串数组)老是存在于堆上,永远不会跑到线程栈.post

C#将String视为基元类型,C#编译器容许在源代码中直接使用字面值字符串.编译器将这些字符串存放到模块的元数据中,并在运行时加载和引用它们.性能

C#不容许使用new操做符从字面值字符串构造String对象,代码以下:ui

相反,必须使用如下简化语法:

 

编译代码并检查IL(使用ILDasm.exe),会看到如下内容:

用于构造对象新实例,但上述代码中并无出现newobj指令,有一个特殊的ldstr(即 load string)指令,它使用从元数据得到的字面值(literal)字符串构造String对象.这证实CLR实际是用一种特殊方式构造字面值String对象

      若是使用不安全的(unsafe)代码,能够从一个Char*或Sbyte*参数构造一个String.这时要使用C#的new操做符,并调用由String类型提供的、能接受Char*或Sbyte*参数的某个构造器.这些构造器将建立String对象,根据由Char实例或有符号(signed)字节构成的一个数组来初始化字符串。其余构造器则不容许接受任何指针参数,用任何托管编程语言写的安全(可验证)代码都能调用它们.

 

二、关于特殊字符的处理:

C#提供了一些特殊的语法来帮助开发人员在源代码中输入字面值(literal)字符串,对于换行符、回车符和退格符这样的特殊字符,C#采用的是C/C++开发人员熟悉的转移机制,代码以下:

//包含回车符和换行符的字符串
string s="Hi\r\nthere.";

 

 三、关于字符串链接的问题

string s="Hi"+" "+"there .";

在上述代码中,因为全部字符串都是字面值,因此C#编译器能在编译时链接它们,最终将一个字符串即(即"Hi there.")放到模块的元数据中.对非字面值字符串使用+操做符,链接则在运行时进行.运行时链接不要用+操做符,由于这样会在堆上建立多个字符串对象,而堆是须要垃圾回收的,对性能有影响.相反,应该使用StringBuilder类型.

 

四、字符串@转义符

C#提供了一种特殊的字符串声明方式.采起这种方式,印号之间的全部字符都会被视为字符串的一部分.这种特殊声明称为"逐字字符串",一般用于指定文件或目录的路径,或者与正则表达式配合使用。如下代码展现了如何使用和不适用逐字字符串字符(@)来申明同一个字符串,代码以下:

//指定应用程序路径,使用\解析'\'
string file="C:\\Windows\\System32\\Notpad.exe";

//使用逐字字符串制定应用程序路径
string file=@"C:\Windows\System32\Notepad.exe";

两种写法生成彻底同样的字符串,但后者的可读性更好.

 

五、字符串是不可变的

string对象最重要的一点就是不可变性.也就是所,字符串一经建立遍不能修改其中的任何字符.是字符串不可变有几方面的好处.

字符串不可变有几个方面的好处:

(1)、它容许在一个字符串上执行各类操做,而不实际地更改字符串,以下代码:

            //建立一个字符串
            string str = "zhengchao";
            //而后将字符串转大写,ToUpperInvariant会建立一个临时字符串,垃圾回收器会在下次回收时回收
            var result = str.ToUpperInvariant();
            //输出:false,说明ToUpperInvariant返回了一个新的字符串
            Console.WriteLine("str:'{0}' is Equals result? The answer is {1}",str, ReferenceEquals(str, result));

            //字符串截取,ToUpperInvariant会建立一个临时字符串,垃圾回收器会在下次回收时回收
            var result1 = result.Substring(2,3);
            //输出:false,说明Substring返回了一个新的字符串
            Console.WriteLine("str is Equals result? The answer is {0}", ReferenceEquals(result, result1));

            //EndsWith对目标字符进行检查不会建立临时字符串
            var result2 = result.EndsWith("ENG");

代码不会长时间引用由ToUpperInvariant和Substring建立的两个临时字符串,垃圾回收器会在下次回收时回收它们的内存.若是执行大量字符串操做,会在堆上建立大量String对象,形成更频繁的垃圾回收,从而影响应用程序性能.so,要高效执行大量字符串操做,建议使用StringBuilder类.

字符串的不可变意味着在操纵或访问字符串时不会发生线程同步问题.此外,CLR可经过一个String对象共享多个彻底一直的String内容.

这样能减小系统中的字符串数量一从而节省内存一这就是所谓的"字符串留用".

 

(2)、实例惟一性

在内存中复制同一个字符串的实例纯属浪费,由于字符串是"不可变"的.在内存中只保留字符串的一个实例将显著提高内存的利用率。须要引用字符串的全部变量只需指向单独的一个字符串对象.

代码以下:

string str1 = "xiaochao";
string str2 = "xiaochao";
Console.WriteLine(ReferenceEquals(str1, str2));//输出:True,说明str1和str2实例指向的是同一个对象

 

出于对性能的考虑,String类型与CLR紧密集成.具体地说,CLR知道String类型中定义的字段如何布局,会直接访问这些字段.可是为了得到这种性能和直接访问的好处,String只能是密封类.换言之,不能把它做为本身类型的基类.

若是容许String做为基类来定义本身的类型,就能添加本身的字段,而这会破坏CLR对于String类型的各类预设.此外还可能破坏CLR团队应为String对象"不可变"而作出的各类预设.

 

六、CLR关于语言文化的类型一CultureInfo类和字符串与线程的关联

 

七、C# 字符串操做基本过程(Equals、Compare、EndsWith等处理方法)

 

八、字符串留用与字符串池

 

九、C# 高效率建立字符串类(StringBuilder).

 

十、C# 获取全部对象的字符串表示一ToString方法

 

十一、C# 自定义类型经过实现IFormattable接口,来输出指定的格式和语言文化的字符串(例:DateTime)

 

十二、C# String.Format的格式限定符与Format方法将多个对象格式化一个字符串原理

相关文章
相关标签/搜索