《CLR via C#》 字符、字符串和文本处理
字符
字符总是表示成16位Unicode代码值,每个字符都是System.Char
接口(值类型)的实例。
Sytem.Char
方法
方法名 | 说明 | |
---|---|---|
GetUnicodeCategory | 返回UnicodeCategory枚举,表明该字符是由Unicode标准定义的控制字符、货币符号、小写字母、大写字母、标点符号还是其他字符。 | |
ToLowerInvariant | 忽略语言文化将字符转换位小写 | |
ToLower | 转换小写,但会使用与调用线程关联的语言文化信息(System.Threading.Thread 的静态属性CurrentCulture ) |
|
Equals | 两个Char实例代表同一个16位Unicode码位的前提下返回true | |
CompareTo | 两个Char实例忽略语言文化的比较结果 | |
GetNumericValue | 返回字符的数值形式 |
Char实例的相互转换
- 转型(强制类型转换):是效率最高的,因为编译器会生成中间语言指令来执行转换,而且不必调用方法。
- 使用
Convert
类:System.Convert
提供了几个静态方法来实现Char和数值类型的转换。所有转换都以checked方式执行,发现转换将造成数据丢失就会抛出OverflowException异常。 - 使用
IConvertible
接口:效率最差,因为再值类型上调用接口方法会装箱。而且很多是显式实现的接口。
System.String
字符串构造
C#将String视为基元类型,也就是允许再源代码中直接使用字面值(literal)字符串。编译器将这些字符串放到模块的元数据中,并在运行时加载和引用它们。
逐字字符串(verbatim string):用@
来声明字符串,其字符串中所有的字符都视为一部分。下面的代码在元数据中生成同样的字符串,但是逐字字符串可读性更好。
1string file = "C:\\Windows\\System32\\Notepad.exe";
2string file = @"C:\Windows\System32\Notepad.exe";
字符串是不可变的
字符串一经创建便不能更改。使字符串不可变有几点好处
- 允许对字符串进行操作,但不实际更改字符串。
- 在操纵或访问字符串时不会发生线程同步问题。
- 可通过一个String对象共享多个一致的String内容,从而节省内存——字符串留用(string interning)。
比较字符串
判断字符串相等性方法:
- Equals
- Compare
- StartsWith
- EndsWith
出于变成目的比较字符串时,应该用StringComparsion.Ordinal
或者StringComparison.OrdinalIgnoreCase
。忽略语言文化比较最快。
要以语言文化来比较字符串,就应该用StringComparsion.CurrentCulture
或者StringComparison.CurrentCultureIgnoreCase
。
注意
应该用String.ToUpperInvariant
来进行正规化(normalizing)。因为编译器对执行大写比较的代码有优化
注意
CompareTo
默认执行对语言文化敏感的比较,而Equals
执行普通的序号比较
语言文化的字符串比较
System.Globalization.CultureInfo
类表示一个“语言/国家”对。在CLR中每个线程都关联了两个特殊属性,每个属性都引用一个CultureInfo
对象。
CurrentUICulture
属性:获取要向用户显式的资源。多用于GUI或Web窗体中。CurrentCulture
属性:不适合CurrentUICulture
属性的场合就使用该属性。
字符串留用
CLR初始化时会创建一个内部哈希表。键是字符串,而值是对托管堆中String对象的引用。
String
类提供了两个方法,便于你访问这个哈希表
Intern
方法获取一个String,获得它的哈希码。并在内部检查是否有匹配。有就返回当前引用,无则创建字符串副本,并将副本添加到哈希表中,返回对其的引用。IsIntern
方法获取一个String,获得它的哈希码。如果哈希表中没有匹配则返回null。
字符串池
编译器只在模块的元数据中只将字面值字符串写入一次。引用该字符串的所有代码都被修改成引用元数据中同一个字符串。编译器也将当个字符串的多个实例合并成一个实例,显著减少模块大小。
利用StringBuilder高效率构造字符串
StringBuilder
对象包含一个字段,该字段引用了由Char
结构构成的数组。可利用StringBuilder
的成员来高效率的操纵该数组。如果字符串变大,超过了预先分配的大小,则会自动分配一个新的、更大的数组,复制字符,并开始使用新数组,前一个数组会被垃圾回收。
ToString方法
System.Object
定义了一个public
、virtual
、无参的ToString
方法。这个方法代表对象当前值的字符串,而且应该根据语言文化进行格式化。
调试器中变量上方出现的数据提示的文本就是通过调用对象的ToString
方法来获取的。
编码
- UTF-16(Unicode):将每16位字符编码成2个字节。不对字符产生影响,也不发生压缩————性能出色。
- UTF-8:值在0x0080之下的字符压缩成1字节,0x0080~0x07FF转换成2字节。0x0800以上位4字节。代理项对表示成4字节。0x0800以上效率不如UTF-16。
- UTF-32:使用4字节来编码所有字符。
- ASCII:将16位字符编码范围只有0x00~0x7F