C#基礎知識-引用類型和值類型的區別(六)
在第一篇中我們介紹了C#中基本的15種數據類型,這15種數據類型中又分為兩大類,一種是值類型,一種是引用類型。值類型有sbyte、short、long、int、byte、ushort、uint、ulong、float、double、bool,引用類型有object、string、class類型,這兩大類最大的區別就是在內存中存儲的位置、方式不一樣。(當我們打開運行一個程序的時候,實際上就會把當前程序需要執行的資源從硬盤加載到內存中,再把內存的數據送去CPU處理),現在來看一下它們是如何來進行存儲的:
//引用類型
publicclassTestObject
{
publicintNumberA;
}
//值類型
publicstructTestValue
{
publicintNumberB;
}
在程序入口處調用:
staticvoidMain(string[]args)
{
//創建一個TestObject對象,命名obj1
TestObjectobj1 = newTestObject();
//創建一個TestValue對象,命名value1
TestValuevalue1 = newTestValue();
//為變量NumberA賦值
obj1.NumberA = 1;
//為變量NumberB賦值
value1.NumberB = 6;
//輸出兩個變量的值
Console.Write("obj1={0} , value1={1}",obj1.NumberA, value1.NumberB);
Console.ReadKey();
}
當我們實例化對象時,在內存中是這樣存儲的:
簡單來說,當我們實例化一個對象時如果是值類型那麽這對象中的數據將會和對象一起存儲在內存棧中,如果是實例化一個引用類型的對象時在內存棧中就會保存這個對象在內存堆中的地址。
下面我們繼續實例化兩個同樣的類時看看不同類型的類有什麽區別?
staticvoidMain(string[]args)
{
//創建一個TestObject對象,命名obj1
TestObjectobj1 = newTestObject();
//創建一個TestValue對象,命名value1
TestValuevalue1 = newTestValue();
//為變量NumberA賦值
obj1.NumberA = 1;
//為變量NumberB賦值
value1.NumberB = 6;
TestObjectobj2 = obj1;
obj2.NumberA= 111;
TestValuevalue2 = value1;
value2.NumberB= 666;
//輸出兩個變量的值
Console.Write("obj1={0} , value1={1} , obj2={2} , value2={3}",obj1.NumberA, value1.NumberB, obj2.NumberA, value2.NumberB);
Console.ReadKey();
}
到這裏猜猜會輸出什麽值?先思考一下,再看下面的答案。
是的沒錯,結果就是:obj1=111 , value1=6 , obj2=111 , value2=666。
為什麽會出現這樣的結果呢,在上面代碼中明明obj1.NumberA已經賦值了1 但是會被obj2改變,value1和value2卻沒有受到影響,原因就是值類型和引用類型的存儲方式的不同,當你把一個引用類型對象賦值給另外一個引用類型的對象時便把它們都指向了同一個地址,所以改變的是同一個對象的值,下面來看看內存中的示意圖:
當將obj1賦值給obj2時相當於指向了同一個堆中的對象(內存地址)。
string不可變類型
在第一篇中我們還提到了string類型是不可變的類型,例如:
string a=”AAA”;
在內存中開辟了一塊空間存儲字符串”AAA”
string a=”BBB”;
在內存中再開辟一塊空間存儲字符串”BBB”
這樣如果變量a改變了值的話不會像值類型中的變量一樣修改本身的值而且另外劃分一塊空間存儲。
想要詳細了解的小夥伴可以再查查相關的資料。
有興趣的可以關註一下我個人的微信公眾號:
Net之道
C#基礎知識-引用類型和值類型的區別(六)