在C#中值類型的變量直接存儲資料,而引用類型的變量持有的是資料的引用,資料存儲在資料堆中。
常見的值類型資料有:整值型(整形,浮點型,十進制型),布爾類型,枚舉類型;
引用類型有:接口,數組,Object類型,類,委托,字元串,null類型。
在C#中每種類型的存儲方式有兩種:1)配置設定在托管棧中;2)配置設定在托管堆中;
記憶體的配置設定有CLR管理(即公共語言運作時),這兩種方法的差別是:
1)配置設定在托管棧中的變量會在建立它們的方法傳回時自動釋放,例如在一個方法中聲明Char型的變量UserInput=C,當執行個體化它的方法結束時,UserInput變量在棧上占用的記憶體就會自動釋放;
2)配置設定在托管堆中的變量并不會在建立它們的方法結束時釋放記憶體,它們所占用的記憶體會被CLR中的垃圾回收機制釋放。
看下面的代碼:
1 static void Main(string[]
args)
2
{
3
//當nStudent聲明并指派是,這時在托管棧上就會開辟一塊記憶體來存儲nStudent的值,當執行個體化nStudent的Main()方法結束時,
4
//nStudent在托管棧上占用的記憶體會自動釋放。
5
int nStudent =
0;
6
//當聲明strStuName時,這個時候“小明”存儲在托管堆中,而托管棧中存儲的是strStuName指向的引用。
7
string strStuName =
"小明";
8
9
Console.WriteLine("學生的總數是{0},五号的名字是{1}", nStudent,
strStuName);
10
Console.ReadKey();
11 }
裝箱和拆箱
當值類型的資料轉換成引用類型時,CLR會先在托管堆配置一塊記憶體,将值類型的資料複制到這塊記憶體,然後再讓托管棧上的引用類型的變量指向這塊記憶體,這樣的過程稱為裝箱。相反的話,有引用類型轉換成值類型的話就稱為拆箱。
一般情況下,.NET會主動的幫我們完成裝箱操作,但是拆箱并非主動,我們必須知道拆箱對象的實力類型,然後明确的去執行拆箱操作。
因為花費了更多的時間,是以裝箱和拆箱對程式的性能有一定的影響。
--------------------------------------------------------------------------------------------------------------------------------------
類型推斷
在C#中有兩種類型的資料,一種是值類型,另一種是引用類型。
值類型包括:内置值類型、使用者自定義值類型、和枚舉,如 int,float
bool 等,以及struct等。
引用類型包括接口類型、使用者自定義的類、委托等。如 string
、DateTime、數組等。
值類型是存儲在堆棧中,而引用類型是存儲在托管堆上,C#程式首先被編譯成IL程式,然後在托管執行。值類型直接從堆棧中裡面取值,而引用類型必須要先從堆棧裡面取出它的位址,再根據這個位址在堆裡找到對應的值。
值類型與飲用類型的本質差別有以下幾點:
1.記憶體配置設定:
值類型是配置設定在棧中的;而引用類型是配置設定在堆中。
2.效率:
值類型效率高,不需要位址轉換;引用類型效率較低,需要進行位址轉換。
3.記憶體回收:
值類型使用完後立即回收;引用類型使用完後不立即回收,而是交給GC處理回收。
4.指派操作:
值類型是建立一個新對象;引用類型建立一個引用。
5.類型擴充:
值類型不易擴充,所有值類型都是密封(seal)的,是以無法派生出新的值類型;引用類型具有多态的特性友善擴充。
這是别人的總結,我在這裡拿來用下。
下面我在說說它們在用法上的差別了,C#之是以要分這兩種資料類型的原因是達到更好的性能,把一些基本類型如int、bool規定為值類型,而把包含許多字段的較大類型規定為引用類型,如使用者自定義的類。值類型主要是負責存儲資料,引用類更多是用在代碼的重用性上。
從C#3.0開始,C#引入了一個隐式類型推斷的關鍵字var,編譯器可以通過它的初始值來判斷變量的具體類型。var隻能用于局部變量的聲明,不能用于字段級的變量聲明。使用var關鍵字時,var必須得有初始值,這樣編譯器才能判斷是否是真實變量。
1 class Program
2
3 static void Main(string[]
4
var i =
10;//隐式類型
int m =
10;//顯示類型
7
8
var Program=new
Program();
Program.nAge =
20;
Program.SayHello();
11
}
12
13 private int
nAge;
14 public void
SayHello()
15
16
var message = "my age is
{0}";
17
Console.WriteLine(message,
nAge);
18
19 }
message初始值的變量為字元串類型,是以編譯器可以推斷其類型為String類型