值型別和引用型別的區別

2021-04-14 06:16:46 字數 1992 閱讀 9464

在開始**.net framework的底層型別系統時,常常會聽到一些相互矛盾的說法。一方面,「所有的型別都繼承於object類」,另一方面「在值型別和引用型別之間轉換時要特別小心」。搞清楚這些說法的關鍵在於,要記住——每種型別,無論是內建的結構,如整型或字串型,還是定製類,如myemployee,都繼承於object類。值型別和引用型別的主要區別在於底層實現方式的不同。

值型別和引用型別的區別是乙個很好的學習起點,因為這是乙個相對簡單的區別。更重要的是,作為.net開發人員,如果編寫的不是效能要求特別高的**,一般不需要注意這個區別。

在把資料賦給值型別和引用型別的時候,兩者表現完全不同:

●       在把資料賦給乙個值型別時,資料儲存在堆疊上的變數中。

●       在把資料賦給乙個引用型別時,變數中只儲存乙個引用,資料則儲存在託管堆上。

理解堆疊和堆之間的區別是非常重要的。堆疊是乙個比較小的記憶體區域,程序和執行緒在其中儲存大小固定的資料塊。例如,無論資料的實際值是多少,儲存整數和小數型別所需要的位元組數都不會變化。因此這種變數在堆疊中的位置可以高效地確定(當乙個過程需要提取某個變數時,就必須搜尋堆疊。如果堆疊包含的變數具有動態的記憶體大小,這種搜尋就需要較長的時間)。

引用型別沒有固定的大小。例如,字串的大小可以在2位元組到接近系統中所有的可用記憶體之間變化。引用型別大小的不確定性意味著,它們包含的資料更適合儲存在堆上,而不是堆疊上,但是,引用型別的位址(即資料在堆上的位置)有固定的大小,所以可以儲存在堆疊上。把引用儲存在堆疊上,整個程式的執行速度會快得多,因為程序可以快速定位與變數中的資料。

固定大小的變數和大小動態變化的變數分別儲存在堆疊和堆上,會使對這兩種變數的操作方式產生差異。下面通過比較system.drawing.point結構(一種值型別)和system.text. stringbuilder類(一種引用型別)來說明這一點。

point結構是.net圖形庫的一部分,而該圖形庫是system.drawing命名空間的一部分。stringbuilder類是system.text命名空間的一部分,用於高效地編輯字串。命名空間將在第8章論述。

下面先看看如何使用system.drawing.point結構:

dim ptx as new system.drawing.point(10, 20)

dim pty as new system.drawing.point

pty = ptx

ptx.x = 200

console.writeline(pty.tostring())

這個運算的輸出是,這看起來是符合邏輯的。**在將ptx複製到pty後,包含在ptx中的資料就複製到堆疊上與pty相關的位置上。當改變ptx的值時,只有堆疊上與ptx相關的記憶體被更新,改變ptx的值不會影響pty。但引用型別不是這樣。考慮下面的**,它使用了system.text.stringbuilder類:

dim objx as new system.text.stringbuilder("hello world")

dim objy as system.text.stringbuilder

objy = objx

objx.replace("world", "test")

console.writeline(objy.tostring())

這段**的執行結果是hello test,而不是hello world。從上面使用point示例可以看出,在把乙個值型別賦給另乙個值型別時,會複製儲存在堆疊上的資料。因此,在前乙個例子中,將objy賦給objx時,堆疊上與objx相關的資料會複製到堆疊上與objy相關的資料上。但是,在本例中,複製的不是實際的資料,而是儲存在託管堆上的資料的位址,即objx和objy現在引用的是相同的資料。當堆上的資料發生變化時,如果某個變數儲存了對該記憶體的引用,則與該變數相關的資料就會發生變化。這就是引用型別的預設操作方式,稱為淺度複製(shallow copy)。本章的後面將論述字串上的這個操作方式是如何被重寫來執行深度複製的。

值型別和引用型別之間的差異不僅僅是在複製時它們的表現不同。本章的後面將討論物件所提供的其他功能。下面先看看最常用的值型別,理解.net是如何使用它們的。

值型別和引用型別區別

3.1.3 值型別和引用型別的區別 37 值型別和引用型別的基本概念 值型別和引用型別的記憶體分配 值型別的基類 分析問題 所有.net 的型別都可以分為兩類 值型別和引用型別。最簡單也最明確的乙個區分標準是 所有的值型別都繼承自 system.valuetype system.valuetype ...

值型別和引用型別區別

3.1.3 值型別和引用型別的區別 37 值型別和引用型別的基本概念 值型別和引用型別的記憶體分配 值型別的基類 分析問題 所有.net 的型別都可以分為兩類 值型別和引用型別。最簡單也最明確的乙個區分標準是 所有的值型別都繼承自 system.valuetype system.valuetype ...

引用型別和值型別區別

1.普通的資料型別,和結構體 列舉等,是值型別,賦值時,會建立乙個備份,給新的變數。2.類 物件是引用型別,賦值時,並不會新建物件的副本,而是把物件的位址給新物件名。所以,物件名中儲存的並不是完整物件的內容,只儲存了找到這個物件的位址。3.sets 集 3.1概念 相同型別 沒有固定順序 數值不能重...