要了解值類型和引用類型,我們首先要知道堆和棧的區別:
① 棧是編譯期間就分配好的內存空間,因此你的代碼中必須就棧的大小有明確的定義;堆是程序運行期間動態分配的內存空間,你可以根據程序的運行情況確定要分配的堆內存的大小
②存放在棧中時要管存儲順序,保持著先進后出的原則,它是一片連續的內存域,由系統自動分配和維護。
而堆是無序的,它是一片不連續的內存域由有用戶自己來控制和釋放,如果用戶自己不釋放的話,當內存達到一定的特定值時,通過垃圾回收器(GC)來回收。
C#的值類型包括:結構體,枚舉,可空類型,byte,short,int,long,float,double,decimal,char,bool ;值類型是存儲在數據棧上的;
C#的引用類型包括:數組,用戶定義的類、接口、委托,object,字符串,引用類型存儲在堆上。
了解了以上區別后,我們通過實例來展示下使用的區別:
引用類型舉例:下面定義兩個byte數組,交換下下標一致的數據:
代碼如下:
static void Main(string[] args){byte[] a = new byte[] { 1, 2, 3, 4, 5 };byte[] b = new byte[] { 6, 7, 8, 9, 10 };ChangeData(a, b);Console.Write($"a數組的值:");for (int i=0;i< a.Count();i++){Console.Write($"{a[i]} ");}Console.WriteLine("\n ***********");Console.Write($"b數組的值:");for (int i = 0; i < b.Count(); i++){Console.Write($"{b[i]} ");}Console.ReadKey();}private static void ChangeData(byte[] aaa, byte[] bbb){int tempa = aaa.Count();int tempb = bbb.Count();int count = tempa > tempb ? tempb : tempa;byte temp = 0;for (int i = 0; i < count; i++){temp = aaa[i];aaa[i] = bbb[i];bbb[i] = temp;}}
運行結果:
雖然我們把byte數組傳遞給了方法ChangeData去處理了,但是處理完a,b的數據實現了交換,因為數組是引用類型,所以上例中aaa和a都是指向的同一段地址,所以一個aaa改變后,a數組的值對應的有改變了。
值類型舉例:
static void Main(string[] args){//byte[] a = new byte[] { 1, 2, 3, 4, 5 };//byte[] b = new byte[] { 6, 7, 8, 9, 10 };//ChangeData(a, b);//Console.Write($"a數組的值:");//for (int i=0;i< a.Count();i++)//{// Console.Write($"{a[i]} ");//}//Console.WriteLine("\n ***********");//Console.Write($"b數組的值:");//for (int i = 0; i < b.Count(); i++)//{// Console.Write($"{b[i]} ");//}int a = 5;int b = 8;ChangeValue(a,b);Console.WriteLine($"a的值:{a}");Console.WriteLine($"b的值:{b}");Console.ReadKey();}//private static void ChangeData(byte[] aaa, byte[] bbb)//{// int tempa = aaa.Count();// int tempb = bbb.Count();// int count = tempa > tempb ? tempb : tempa;// byte temp = 0;// for (int i = 0; i < count; i++)// {// temp = aaa[i];// aaa[i] = bbb[i];// bbb[i] = temp;// }//}private static void ChangeValue(int aaa, int bbb){int temp = aaa;aaa = bbb;bbb = temp;}
運行結果:
我們看值交換后aaa和bbb值變化了,原始的a和b的值并沒有變化。