classProgram
{
staticvoid Main()
{
int a = 9; //给变量a赋值为9
int b = a; //将a的副本给变量b
b = 10;
Console.WriteLine(string.Format("a={0},b={1}", a, b));
Person ZS = newPerson(); //张三
ZS.Age = 99; //张三的年龄是99
Person SM = ZS; //三毛等于张三,即张三和三毛就是同一个人
SM.Age = 100; //三毛年龄变成100,张三也就变成了100
Console.WriteLine(string.Format("A={0},B={1}", ZS.Age, SM.Age));
Console.ReadKey();
}
}
classPerson
{
publicint Age { get; set; }
}
相同的结构,不同的结果。
2. 何以证明string是引用类型
区分值类型与引用类型就是看它是值传递还是引用传递,如下:
using System;
classProgram
{
staticvoid Main()
{
int n = 99;
Console.WriteLine("Before:n={0}", n.GetHashCode());
//此时获取到的哈希码值就是n的变量值
GetInt(n);
string s = "Hello";
Console.WriteLine("Before:s={0}", s.GetHashCode());
GetString(s);
Console.ReadKey();
}
staticint GetInt(int n)
{
Console.WriteLine("After:m={0}", n.GetHashCode());
//传过来的是变量值,说明这是值传递
return n;
}
staticstring GetString(string s)
{
Console.WriteLine("After:s={0}", s.GetHashCode());
//传过来的是地址而不"Hello",说明这时引用传递
return s;
}
}
3. string是特殊的引用类型
为什么说string是特殊的引用类型,因为看了下面的运行结果你会很困惑,这是怎么回事呢?且看代码分析:
classProgram
{
staticvoid Main()
{
string a = "Hello ";
Console.WriteLine(a.GetHashCode());
//定义一个变量a,(暂且用哈希码表示地址编号)地址编号为1402305,指向对象的值为“Hello”。
string b = a;
Console.WriteLine(b.GetHashCode());
//把a的地址给b,所以b的地址也是1402305
b = "world";
Console.WriteLine(b.GetHashCode());
//string类型的值三只读的,当给他重新赋值的时候需要额外分配内存,同时地址也发生变化。这也就是string类型和一般引用类型的不同之处
//可以这么理解,字符串变量吃饭用一次性碗筷,这也是为什么在做大量字符串拼接的时候要使用StringBuilder 而不用+=
Console.WriteLine("a:"+a+"\nb:"+b);
//此时有两个地址,分别对应托管堆上两个不同的对象值
Console.ReadKey();
}
}
运行结果:
请思考下面代码的运行结果:
staticvoid Main()
{
string s = "Hello!";
ChangeStr(s);//调用方法
Console.WriteLine(s);
}
staticvoid ChangeStr(string s){s = "你好!";}
答案:?
//ChangeStr方法体内传过来的确实是引用地址,但是由于string是只读的,给他重新赋值的时候又重新分配了新地址,而对原来地址和所对应的值没有影响
那怎么定义string的值传递方法呢?
staticstring ChangeStr(refstring s)
4. string是一个变态类型
说string是特殊的引用类型是出于客气,写到这我就不能不破口大骂string是个变态狂了,Look:
classProgram
{
staticvoid Main()
{
string S1 = "Hello";
string S2 = "Hello";
bool r1 = object.ReferenceEquals(S1, S2);
var A = new { Age = 12 }; //对象A
var B = new { Age = 12 }; //对象B
bool r2 = object.ReferenceEquals(A, B);
Console.WriteLine("r1={0},r2={1}", r1, r2);
Console.ReadKey();
}
}
运行结果真的让人出乎意料,同样是引用类型,string总是和别人不一样。
消消气,理智一点分析,其实这就是string的内存驻留机制 ,也就是CLR为string做的优化(当有多个字符串变量包含了相同的值时, CLR尽可能不要重复地分配内存,而是让它们统统指向同一个字符串对象实例)。
staticvoid Main()
{
string p = "Hello";
string q = new StringBuilder().Append("Hello").ToString();
Console.WriteLine(object.ReferenceEquals(p, q));
//由于声明方式不同,所以CLR不会检查驻留池是否存在相同的变量值
Console.ReadKey();
}
staticvoid Main()
{
string p = "Hello";
string q = new StringBuilder().Append("Hello").ToString();
string o = string.Intern(q); //强制CLR检查驻留池
Console.WriteLine(object.ReferenceEquals(p, o));
Console.ReadKey();
}
---- Author:Hollson QQ:498576940