.NET中的字符串(1):字符串 - 特殊的引用类型
C# string 特殊的引用类型
.Net 框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一个引用类型,也就是说线程上的堆栈上不会驻留有任何字符串。(译注:注意这里的“直接继承”。直接继承自Object的类型一定是引用类型,因为所有的值类型都继承自System.ValueType。值得指出的是System.ValueType却是一个引用类型)。
1
2
3 |
string
str1 = "string" ; string
str2 = "string" ; Console.WriteLine( string .ReferenceEquals(str1, str2)); |
既然String类型是引用类型,那么代码一输出的应该是False,然而事实上代码一输出时的是True。
其实这是String类型的自动优化功能。str1,str2引用同一对象,节省内存,并不会为str2单独开辟内存空间。CLR使用了一种叫字符串驻留的技术,当CLR初始化时,会创建一个内部的散列表,其中的键为字符串,值为指向托管堆中字符串的引用。刚开始,散列表为空,JIT编译器编译方法时,会在散列表中查找每一个文本常量字符串,首先会查找"abc"字符串,并且因为没有找到,编译器会在托管堆中构造一个新的指向"abc"的String对象引用,然后将"abc"字符串和指向该对象的引用添加到散列表中。接着,在散列表中查找第二个"abc",这一次由于找到了该字符串,指向同一个String对象的引用会被保存在变量str2中,到此str1和str2指向了同一个引用,所以string.ReferenceEquals(str1, str2)就会返回true了。
另外,C#中是不允许用new操作符创建String对象的,编译器会报错。
1
2
3
4
5
6
7
8 |
static
void Main( string [] args) { string
str = "string" ; Change(str); Console.WriteLine(str); } static
void Change( string
str) { str = "Changed" ; } |
方法传递的参数是原内容的拷贝,其过程如果用图可表示为:
语句str=”Changed”之前
语句str=”Changed”之后
这样可以看到原来String对象并未改变str=”Changed”只是创建一个新的String对象(其它引用类型是改变内存地址1指向的值),因此这个方法的参数需要加上ref或者out修饰符。因此这里也可以得出字符串具有恒等性,也就是说一个字符串一旦被创建,我们就不能再将其变长、变短、或者改变其中的任何字符。
MSDN上这样解释:字符串对象是不可变的,即它们一旦创建就无法更改。对字符串进行操作的方法实际上返回的是新的字符串对象。
string在另一种情况下的操作是具有值类型特征的:str1 == str2 ,仅仅是比较了值,而非地址(是MS重写了==运算符所致
String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。在需要对字符串执行重复修改的情况下,与创建新的 String 对象相关的系统开销可能会非常昂贵。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类。例如,当在一个循环中将许多字符串连接在一起时,使用 StringBuilder 类可以提升性能。
下面看一个极简单的例子:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 |
namespace
TCP { public
class Program { public
class User { private
string _name; private
string _age; public
User( string
name, string
age) { _name = name; _age = age; } public
string name { get
{ return
_name; } set
{ _name = value; } } public
string age { get
{ return
_age; } set
{ _age = value; } } } } public
static void editUser(User user, StringBuilder str, string
code) { code = "VB.NET" ; str = str.Remove(0, 1); str.Append( "E" ); user.name = "LEE" ; user.age = "10" ; } static
void Main( string [] args) { string
code = "C#" ; User user = new
User( "Li" , "23" ); StringBuilder str = new
StringBuilder(); str.Append( "A" ); editUser(user, str,code); Console.WriteLine(code); Console.WriteLine(str); Console.WriteLine(user.name); Console.WriteLine(user.age); Console.ReadLine(); } } |
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。