c# 值類型與引用類型的區別(含例子)

c# 值類型與引用類型的區別

參考資料:《C#程序設計》

1、首先我們先了解一下c#的基本數據類型包含哪些。
c#的數據類型可分爲兩種,分別是值類型和引用類型。關係如下圖:
在這裏插入圖片描述
2、什麼是值類型呢?
值類型直接存儲數據值,它主要包括簡單類型和複合類型兩種,其中,簡單類型是程序中使用的最基本類型,主要包括整數類型、浮點類型、布爾類型和字符類型等4種。值類型在棧中進行分配,因此效率很高,使用值類型主要目的是爲了提高性能。值類型具有如下特性。
》值類型變量都存儲在棧中。
》訪問值類型變量時,一般都是直接訪問其實例。
》每個值類型變量都有自己的數據副本,因此對一個值類型變量的操作不會影響其他變量。
》值類型變量不能爲null,必須具有一個確定的值。

3、什麼又是引用類型呢?
引用類型是構建C#應用程序的主要對象類型數據,引用類型的變量又稱爲對象,可存儲對實際數據的引用。C#支持兩個預定義的引用類型object和string。
在應用程序執行的過程中,引用類型使用new關鍵字創建對象實例,並存儲在堆中。堆是一種由系統彈性配置的內存空間,沒有特定大小及存活時間,因此可以被彈性地運用於對象的訪問。
引用類型具有如下特徵。
 必須在託管堆中爲引用類型變量分配內存。
 在託管堆中分配的每個對象都有與之相關聯的附加成員,這些成員必須被初始化。
 引用類型變量是由垃圾回收機制來管理的。
 多個引用類型變量可以引用同一對象,這種情形下,對一個變量的操作會影響另一個變量所引用的同一對象。
 引用類型被賦值前的值都是null。
所有被稱爲“類”的都是引用類型,主要包括類、接口、數組和委託等。例如:

Student student1=new Student();
Student student1=student1;

4、他們的區別是什麼?
先上圖,如下
在這裏插入圖片描述
值類型聲明的變量int a1,a2的值是存儲在棧中的,而引用類型則在棧中存儲引用(地址/URL)指向內存堆中,把值存儲在堆中相應的對象裏。
4.1、概念上講,值類型是直接存儲值的,而引用類型則是對其引用的存儲,存的一個地址,這個地址指向內存堆中相應的對象。
4.2、從內存空間上講,值類型是在棧中操作,而引用類型則在堆中分配存儲單元。棧在編譯的時候就分配好內存空間,在代碼中有棧的明確定義;而堆是程序運行中動態分配的內存空間,可以根據程序的運行情況動態地分配內存的大小。
4.3、因此,值類型總是在內存中佔用一個預定義的字節數,而引用類型的變量則在堆中分配一個內存空間,這個內存空間包含的是對另一個內存位置的引用,這個位置是託管堆中的一個地址,即存放此變量實際值的地方。

5、例子
創建一個控制檯應用程序,首先在程序中創建一個類stamp,該類中定義兩個屬Name和Age,其中Name屬性爲string引用類型,Age屬性爲int值類型;然後定義一個ReferenceAndValue類,該類中定義一個靜態的Demonstration方法,該方法主要演示值類型和引用類型使用時,其中一個值變化時,另外的值是否變化;最後在Main方法中調用ReferenceAndValue類中的Demonstration方法輸出結果。代碼如下。

class Program
{
 static void Main(string[] args)
 {
 //調用ReferenceAndValue類中的Demonstration方法
 ReferenceAndValue.Demonstration();
 Console.ReadLine();
 }
}
public class stamp				//定義一個類
{
 public string Name { get; set; }		//定義引用類型
 public int Age { get; set; }			//定義值類型
}
public static class ReferenceAndValue		//定義一個靜態類
{
 public static void Demonstration()		//定義一個靜態方法
 {
 stamp Stamp_1 = new stamp { Name = "Premiere", Age = 25 };
 stamp Stamp_2 = new stamp { Name = "Again", Age = 47 };
 int age = Stamp_1.Age;			//獲取值類型Age的值
 Stamp_1.Age = 22;			//修改值類型的值
 stamp Stamp_3 = Stamp_2;			//獲取Stamp_2中的值
 Stamp_2.Name = "Again Amend";		//修改引用的Name值
 Console.WriteLine("Stamp_1's age:{0}", Stamp_1.Age);//顯示Stamp_1中的Age值
 Console.WriteLine("age's value:{0}", age); //顯示age值
 Console.WriteLine("Stamp_2's name:{0}", Stamp_2.Name);//顯示Stamp_2中的Name值
 Console.WriteLine("Stamp_3's name:{0}", Stamp_3.Name);//顯示Stamp_3中的Name值
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章