上周研究了下IL,这周在看《你必须知道的.Net》,还有点意思,书中讲了些平时比较少关注的C#的底层特性,今天再来聊聊这个String。
一、字符串特殊性
String类型很特殊,为什么呢?
1.创建特殊性: String 对象不以 newobj 指令创建,而是 ldstr 指令创建。在实现机制上, CLR 给
了特殊照顾来优化其性能。
2.String 类型是.NET 中不变模式的经典应用,在 CLR 内部由特定的控制器来专门处理 String 对象。
3.应用上, String 类型表现为值类型语义;内存上,String 类型实现为引用类型,存储在托管堆中。
4.两次创建内容相同的 String 对象可以指向相同的内存地址。
5.String 类型被实现为密封类,不可在子类中继承。
6.String 类型是跨应用程序域的,可以在不同的应用程序域中访问同一 String 对象。
这是书中的归纳总结,初学者非常容易被String是值类型还是引用类型搞晕,因为String使用起来跟值类型几乎没有什么区别,对于引用类型的"=="与"Equals"方法比较的两个引用类型的地址是否相等,而我们这么写
string a = "unity";
string b = "unity";
Console.WriteLine(a == b);
Console.WriteLine(a.Equals(b));
Console.WriteLine(ReferenceEquals(a, b));
//执行结果:
//True
//True
//True
都返回真,为什么?通常的理解是String类型的"=="与"Equals"比较的是值是否相等,那么ReferenceEquals又如何解释呢?
如果我们把代码改一下
string a = "unity";
string c = "uni";
string b = c + "ty";
Console.WriteLine(a == b);
Console.WriteLine(a.Equals(b));
Console.WriteLine(ReferenceEquals(a, b));
//执行结果:
//True
//True
//False
为什么?
二、字符串恒定性
字符串恒定性(Immutability),是指字符串一经创建,就不可改变。这是 String 对象最为重要的特性之一,是 CLR 高度集成 String 以提高其性能的考虑。具体而言,字符串一旦创建,就会在托管堆上分配一块连续的内存空间,我们对其的任何改变都不会影响到原 String 对象,而是重新创建出新的 String 对象。
string str = "This is a test about immutablitity of string type.";
Console.WriteLine(str.Insert(0, "Hi, ").Substring(19).ToUpper());
Console.WriteLine(str);
//执行结果:
//ABOUT IMMUTABLITITY OF STRING TYPE.
//This is a test about immutablitity of string type.
这段代码会产生多少个临时字符对象?答案是3个,str的结果还是原来的结果,Insert、Substring 和ToUpper 方法都会创建出新的临时,而且因为没有被其他代码引用,会成为内存垃圾,等待下次垃圾回收器回收,造成性能损失