1***、C#中有兩種類型:
值類型和引用類型:
值類型的變量直接包含他們的數據,而引用類型的變量存儲
引用類型存儲對他們的數據的引用,后者稱為對象:
簡單說:值類型直接存儲其值,引用類型存儲對值得引用.引用類型分為引用和引用的對象。
2***、
值類型:簡單類型、枚舉、結構
引用類型: 類類型、接口類型、數組類型和委托類型
3***、值類型與引用類型的內存存儲
單純的說值類型存儲在棧上,引用類型存儲在托管堆上是不對的。
4***、區別:
1、
托管堆: 同步塊和方法表, x,y,托管堆上的需要GC來回收
線程堆棧: 沒有同步塊和方法表
2、
值類型賦值是重新創建一個副本
而引用類型的賦值是共享同一塊內存(副本),是指向同一塊內存(引用類型的名字相當於指向操作)。只是復制引用而不復制被引用識別的對象。(“引用”和“引用的對象”)
3、
值類型與引用類型的不同之處就在於值類型的變量直接包括他們的數據,而引用類型的變量把references存儲到他們的數據庫(Objects)中。
4、
所有的值類型從Object中繼承來的。任何類型都不能由值類型派生而來,因此,值類型是封閉式的。
5***什么時候使用值類型
1)當類型是一個十分簡單的類型,其中沒有成員會修改類型的任何實例字段
2)類型不需要從其他任何類型繼承
3)類型不會派生出其他任何類型
4)類型的實例較小
5)類型不作為方法參數傳遞,也不作為方法的返回類型使用
6)引用類型可以包含null值,值類型不能(可空類型功能允許將null賦給值類型);
6***什么時候用ref和out
ref:值類型在傳遞希望成為引用的時候,ref就是告訴傳遞的時候不是拷貝,而是同一個副本。
out:不需要給變量賦初值,使用out也沒必要在外面賦初值,是在內部賦“初值”,out傳遞值是理解成沒有初始化的。
7***深度分析值類型和引用類型(內存中的部署)
例子:Objectreference r = new object();
關鍵字new在托管堆上分配內存空間,並返回一個該內存空間的地址。左邊的reference位於棧上,是一個引用,存儲着一個內存地址;而這個地址指向的內存(位於托管堆上)里存儲着其內容。
規律:
1)引用類型部署在托管堆上
2)值類型總是分配在它聲明的地方:作為字段時,跟隨其所屬的實例存儲。作為局部變量時,存儲在棧上。
總結: 引用類型在棧上存儲一個引用,其實際的存儲位置位於托管堆。
8***裝箱與拆箱操作
1) 裝箱操作
裝箱(box)就是將值類型轉換為引用類型的過程。而相反的過程就叫拆箱(unbox)。
裝箱時發生了什么?
(1)在堆上分配內存。因為值類型最終有一個對象代表,所有堆上分配的內存量必須是值類型的大小加上容納此對象及其內部結構(比如虛擬方法表)所需的內存量。
(2)值類型的值被復制到新近分配的內存中
(3)新近分配的對象地址被放到堆棧上,現在它指向一個引用類型。
2)拆箱操作
注:被裝過箱的對象才能被拆箱。
在裝箱的時候,並不需要顯示類型轉換.但在拆箱時需要類型轉換.這是因為在拆箱時對象可以被轉換為任意類型.
注意:裝箱操作可以隱式進行,但拆箱操作必須顯示。
首先,檢查這個對象實例,看它是否為給定值類型的裝箱值。
然后,把這個實例的值拷貝給值類型的變量。
要盡量減少裝箱與拆箱操作
9***問題
1)C#中null和""的區別
string是引用類型:
string str= null 沒有創建內存空間,str中存放的是空引用指針.
string str="" str中存放的是指向堆中的指針。有指向
簡單地說:
string str ="";
給你一張白紙;
string str = null;
連白紙也沒有。
string.Empty就相當於"" 一般用於字符串的初始化
判定為空字符串的幾種寫法,按照性能從高到低的順序是:
s.Length == 0 優於 s == string.Empty 優於 s == ""
2)C#里面的垃圾回收
GC(垃圾回收)回收的都是可托管代碼,也就是托管堆中的代碼
一般定義一個引用變量,它肯定會在堆上面占用一塊空間,棧上有個地址指向這個存儲位置,只有當GC發現堆上這個資源在棧上沒有地址指向它的時候才把這塊內存回收。
非托管資源GC是不會自動回收的,例如數據庫鏈接,文件等。
相關文章:
http://www.cnblogs.com/siqing99/archive/2012/04/03/2430918.html
