標籤:
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中存放的是Null 參考指標. string str="" str中存放的是指向堆中的指標。有指向 簡單地說: string str =""; 給你一張白紙; string str = null; 連白紙也沒有。 string.Empty就相當於"" 一般用於字串的初始化 判定為空白字串的幾種寫法,按照效能從高到低的順序是:s.Length == 0 優於 s == string.Empty 優於 s == "" 2)C#裡面的記憶體回收 GC(記憶體回收)回收的都是可Managed 程式碼,也就是託管堆中的代碼 一般定義一個引用變數,它肯定會在堆上面佔用一塊空間,棧上有個地址指向這個儲存位置,只有黨GC發現堆上這個資源在棧上沒有地址指向它的時候才把這塊記憶體回收。 非託管資源GC是不會自動回收的,例如資料庫連結,檔案等。
C#參考型別和實值型別的區別