案例:以下展示了三个类型的两变量赋值。int类型,string类型,类类型
在赋值上,表面上看string类似值类型int.但string是一个引用类型,编译器对其做了特殊处理。
static void Main(string[] args) { //值类型的赋值 int a = 1; int b = a; a = 2; // a=2;b=1; Console.WriteLine($"a={a};b={b}"); //string类型的赋值 string str1 = "ab"; string str2 = str1; str1 = "abc"; // str1=abc;str2=ab; Console.WriteLine($"str1={str1};str2={str2}"); //类类型的赋值 HashSet<People> list = new HashSet<People>(); var temp = new People() { Name = "Jock", Age = 19 }; var temp1 = temp; temp.Name = "Admin"; //temp={"Name":"Admin",Age=19} //temp={"Name":"Admin",Age=19} Console.WriteLine($"temp={JsonSerializer.Serialize(temp)}"); Console.WriteLine($"temp1={JsonSerializer.Serialize(temp1)}"); Console.Read(); }
结论:
不同的 string 变量,相同的值,其引用地址相同;
(两个string 变量,如果赋值为同一个 串,在内存中只有一个字符串存在,两个应用的地址相同,由此引出string的不变性)
string的不变性:
我们一但建立了一个string,在managed heap(托管堆)上为他分配了一块连续的内存控件,我们将不能以任何方式对这个string进行修改使它变长、变短,改变内容;所有对这个string进行的各项操作(eg:ToUpper获取大写格式的string),实际上是重新创建一个新的string对象,其本身不会产生任何变化。
string对象称为不可变的(只读),但string的不变,并非说string不能改变,而是其值不能改变。
在例子中 str1 ="ab",这时在内存中就将 "ab"存下来,如果再创建字符串对象str2,其值也等于"ab",则并非在重新分配内存空间,而是将之前保存的“ab”的地址赋值给str2的引用。而当 str1="abc"其值发生改变时,这时检查内存,发现不存在此字符串,则重新分配内存空间,存储“abc”,并将其值赋值给str1.而str2依然指向"ab"的地址。