第十四章 字符串 第十五章 枚举和位标志

1. 字符 Char

字符是值类型,16位的Unicode编码.

Char.GetUnicodeCategory返回字符类型的枚举.

2. String

是一个引用类型,代表一个不可变的顺序字符集.分配在堆上.

C#编译器把String作为一个基元类型,可以直接定义文本常量,=,

Environment.NewLine返回由回车和换行符组成的一个字符串,如 : var s = "s" + Environment.NewLine + "";

尽量避免使用+操作符连接几个字符串.会分别创建字符串的.

String.clone和Tostring返回对同一个对象的引用,静态方法Copy返回一个含有相同字符的不用引用.

String 比较

string.Compare静态方法和StringComparison.要考虑CultureInfo的异同.

CultureInfo.CurrentUICulture和CultureInfo.CurrentCulture.

CultureInfo.CompareInfo.Compare

字符串留用

CLR创建一个哈希表,Key是字符串,Value是字符串的引用.垃圾回收器不能释放这些字符串,在AppDomain卸载时才会释放.

String.Intern 检索系统对指定 System.String 的引用,如果暂存了 str,则返回系统对其的引用;否则返回对值为 str 的字符串的新引用(创建副本,将副本加入哈希表)
string.IsInterned 如果 str 在公共语言运行时的暂存池中,则返回对它的引用;否则返回 null

System.Runtime.CompilerServices.CompilationRelaxationsAttribute控制由公共语言运行时的实时 (JIT) 编译器生成的代码的严格性.

System.Runtime.CompilerServices.CompilationRelaxations.NoStringInterning将程序集标记为不需要字符串暂留.这两个字段可设置程序集是否留用字符串.

CLR默认留用程序集中的源数据描述的文本常量.永远都不要以”字符串已留用”为前提进行编程,除非显示调用字符串留用.

var s1 = "hello";
var s2 = "hello";
var result = object.ReferenceEquals(s1, s2);
Console.WriteLine(result);

输出为True(在2.0版本也是True…个人认为这个是因为字符串池的原因,不是字符串留用的原因,元数据信息中只有一个string)

var t1 = new string('s', 5);
var t2 = new string('s', 5);
result = object.ReferenceEquals(t1, t2);
Console.WriteLine(result);

输出为False

字符串池

如果代码中有对一个字符串的多次引用,编译器会只在元数据中插入文本常量字符串,使用字符串的地方只是引用这个元数据中的字符串.这也能说明上边第一个代码输出为True的原因.

文本元素(抽象字符)

System.Globalization.StringInfo 提供功能将字符串拆分为文本元素并循环访问这些文本元素

3.StringBuilder

内部包含一个Char数组,有一个最大容量和倍增容量.

可以高效的操作字符串,不会导致多次的开辟新的字符串.

如果字符串的长度超过了Builder的设置长度,会导致重新分配内存有一个疑问,是重新分配Build的内存还是Char数组的内存,应该是重新分配的Char数组的内存.

4.ToString

调试器中鼠标移动到一个变量上方显示出来的提示,是调用对象的ToString方法获得的.

使用System.Globalization.CultureInfo.InvariantCulture来获得字符串的无具体语言文化的格式.

自定义FormatProvider实现指定格式的ToString,使用到的类有IFormatProvider,ICustomFormatter.IFormattable

NumberFormatInfo格式化数字,DateTimeFormatInfo格式化日期和时间,CultureInfo特定文化,ICustomFormatter自定义格式.

其中IFormattable(提供将对象的值格式化为字符串表示形式的功能),支持enumeration,numeric,date,time,timespan.String是不支持IFormattable的,没有实现这个接口.

5. 编码和解码

UTF-16也称为Unicode编码,每个16位字符编码成2个字节.

字节流的解码

假如通过NetWorkStream的方式读取字符串,可能以数据块的方式传递,第一次读取5个字节,第二次读取7个字节,这样会导致字节丢失.可以使用Decoder类解决,第一次解码剩下的一个字节会在解码下一个的时候加上.

6. 安全字符串

String对被垃圾回收之后,内存可能无法立即重用,导致字符串长时间留在内存中,引起不安全的因素.

System.Security.SecureString是安全字符串.在Dispose的时候,数据会被清0.字符串不再存在于内存中.

Marshal提供了对于他的一些操作方法.

7. 位标志和枚举方法

可以向枚举添加方法,使用扩展方法的方式添加.

8. 数组

所有数组都隐式实现Array类

Array.Copy是浅拷贝.

Array.CreateInstance可以创建下标大于0的数组,如:    Array.CreateInstance(typeof(double), new int[] { 2, 2 }, new int[] { 2000, 3000 });,GetLowerBound获取数组下标.

stackalloc在栈上分配内存块.

原文地址:https://www.cnblogs.com/zhangliming/p/3481975.html