在C#中String是一个特殊的引用类型,但是他的使用和值类型相似!
String s = new String("aaa");
是错误的
只能这样写:
String s = new String("aaa");
为什么呢?
可以看看ILDase.exe中生成的IL代码:
ldstr "aaa"
我们知道构造一个实例的IL指令为:newobj,而ldstr是load string的意思,
也就是说实际上.NET是通过从元数据中获的的文本常量来构造String的。
也就是说还有更高效的String类型,就是StringBuilder。
====================================================================
那么他是怎么判断二者相等的呢?
比如:
String s = "aaa";
Console.WriteLine( Object.ReferenceEquals("aaa",s) );
可能会认为他会返回false,事实上返回的true;
为什么呢?
在CLR初始化时,会创建一个散列表,其中键为string类型,值为指向托管堆中string对象的引用,开始散列表为空!对于上面的代码,编译时候,她在散列表中查找每一个文本常量string,他首先会查找第一个“aaa”,因为没有找到,所以会构造一个,然后把"aaa"和指向他的引用添加到散列表中,接着查找第二个“aaa”,这一次因为可以找到,所以什么也不做;
代码开始执行了,他会在第一行发现需要一个“aaa”字符串引用,于是CLR就在散列表中查找“aaa”,当然可以找到,找到后,就把散列表中“aaa”所在的引用存储到了s中,当执行第二行代码时候,他还会执行查找的过程,并且还会找到,而且同样的把散列表中“aaa”所在的引用传出来,也就是说作为了ReferenceEquals中的第一个参数,OK,因为二者指向的应用相同,所以返回了True!