简介1中详细的介绍了值类型和引用类型的Equals比较。今天来谈一谈String类型。
1. String细节科普
按照惯例,科普一下String引用类型知识:
String驻留(不变性):
string a="123";
实际上相当于在堆中开辟了一块内存用来存放"123"。由于在程序中"123"字符串会频繁使用,C#为了优化性能,就设计了一个表,表结构类似于Dictionary类的key,value形式,key:存放值,value:存放值得引用。当我们在程序用再次使用"123"这个字符串时,C#就会在这个表中进行匹配,如果找到了,就把value所存的引用地址返回给所声明的变量,这样就不用重新开辟内存。如果没有找到,则new一个新内存,存放值,并且以key,value的形式存放在该表中,方便下次重用。
String中的特殊情况
当然,并不是所有的情况都适用于String驻留,其中有一种特殊的是字符串拼接。
比如:
string a="1";
a+="23";
一旦拼接字符串,在指令级别所执行的代码与string驻留是不一样的,string驻留在IL(中间语言)中执行,类似于strloc的代码,拼接则不同有兴趣的同学自己查一下IL。
而一旦拼接字符串,就会在堆中开辟新的内存,地址也是新的地址,这块新内存的值跟string所存储的那张表就没有任何关系了(执行的指令不一样,根本就不会去那张表进行数据匹配),所以,千万不要频繁拼接字符串!!!
比如说变量a,先开辟了一块内存里面存放1,然后在开辟一块新内存存放123,每一次拼接必然开辟新内存存储,极为消耗内存。
2. String 实战
数据类型比较依据表:
|
== |
equals |
ReferenceEquals |
值类型 |
值 |
值 |
地址 |
引用类型(除String) |
地址 |
地址 |
地址 |
String |
值 |
值 |
地址 |
private static void StringEqualsTest2()
{
string a = "123";
string b = "123";
string c = "1";
c += "23";
string d = "12";
d += "3";
//值比较
Console.WriteLine(a == b);
Console.WriteLine(a == c);
Console.WriteLine(c == d);
Console.WriteLine(a.Equals(b));
Console.WriteLine(a.Equals(c));
Console.WriteLine(c.Equals(d));
Console.WriteLine(string.Equals(a,b));
Console.WriteLine(string.Equals(a,c));
Console.WriteLine(string.Equals(c,d));
Console.WriteLine("---------------------------");
//内存地址比较
Console.WriteLine(object.ReferenceEquals(a, b));
Console.WriteLine(object.ReferenceEquals(a, c));
Console.WriteLine(object.ReferenceEquals(c, d));
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
执行结果如图:
- 分割线以上:
解释:是因为string类重写了==,!=,Equals方法,使其像值类型一样,只比较所存的值 - 分割线以下:
解释:第一个True是因为string驻留,其他两个False是因为拼接字符串导致。
|