值型別和引用型別區別

2021-06-22 03:58:16 字數 2882 閱讀 1077

3.1.3 值型別和引用型別的區別 37

· 值型別和引用型別的基本概念

· 值型別和引用型別的記憶體分配

· 值型別的基類

分析問題

所有.net

的型別都可以分為兩類:值型別和引用型別。最簡單也最明確的乙個區分標準是:所有的值型別都繼承自

system.valuetype

(system.valuetype

繼承自system.object

),也就是說,所有繼承自

system.valuetype

的型別都是值型別,而其他型別都是引用型別。常用的值型別包括結構、列舉、整數

型、浮點型、布林型等,而在

c#中所有以

class

關鍵字定義的型別都是引用型別。

嚴格來說,

system.object

作為所有內建型別的基類,本身並沒有值型別和引用型別之分。但是

system.object

的物件,具有引用型別的特點。這也是值型別在有些場合需要裝箱拆箱操作的原因。

1.賦值時的區別

引用型別和值型別最顯著的乙個區別在於變數的賦值問題。值型別的變數將直接獲得乙個真實的資料副本,而對引用型別的賦值僅僅是把物件的引用賦給變數,這樣就可能導致多個變數引用到乙個實際物件例項上。

來看一段簡單的示例:**

3-2。首先為了測試建立乙個簡單的引用型別和乙個簡單的值型別。

**3-2  

值型別引用型別賦值:

valueref.cs

///

/// 

乙個簡單的引用型別

///

public class ref

public int i

set}

public override string tostring()

}///

/// 

乙個簡單的值型別

///

public struct val

public int i

set}

public override string tostring()

}隨後編寫

main

方法,測試對值型別和引用型別物件進行賦值的不同結果,如**

3-3所示。

**3-3  

值型別引用型別賦值:

valueref.cs

public class valueref

}簡單分析一下**

3-2和**

3-3,程式定義了乙個引用型別

ref和乙個值型別

val,兩者的內容幾乎完全相同。在

main

方法中,分別測試了引用型別

和值型別的賦值。當**把乙個引用型別變數賦值給另乙個引用變數:

ref ref2=ref1

時,實際上把

ref1

的物件引用賦給了

ref2

,這樣,兩個引用變數實際指向了同乙個物件。而值型別的賦值則不同,

val1

和val2 

都保留了屬於自己的資料副本,所以當

val2

改變時,

val1

不受到影響。以下是**

3-2和**

3-3的輸出結果:

ref1 i 

的值為:

2ref2 i 

的值為:

2val1 i 

的值為:

1val2 i 

的值為:22

.記憶體分配的區別

除了賦值的區別,引用型別和值型別在記憶體的分配位置上也有區別。引用型別的物件將會在堆上分配記憶體,而值型別的物件則會在堆疊上分配記憶體。堆疊的空間相對有限,但執行效率卻比堆高得多,關於堆和堆疊的特點,將在本章的後續章節中有詳細的說明。

3.來自繼承結構的區別

最後,由於所有的值型別都有乙個共同的基類:

system.valuetype

,所以值型別擁有一些引用型別不具有的共同性質,較重要的一點是值型別的比

較方法:

equals

方法的實現有了改變。在前文中筆者已經談到,所有的值型別已經實現了內容的比較,而引用型別在沒有重寫

equals

方法的情況下,仍

然採用引用比較。**

3-4展示了這個特性,**

3-4仍然使用了**

3-2中建立的值型別和引用型別,這裡不再重複列出這兩個型別的定義。

**3-4  

值型別引用型別比較:

valuerefequals.cs

using system;

using system.collections.generic;

using system.text;

namespace net.mst.third.valuerefequals}}

在main

方法中,分別申明了一對內容完全相同的值型別物件和引用型別物件,呼叫

equals

方法來比較,發現值型別物件比較返回

true

,而引用型別物件比較返回

false

。以下是**

3-4的執行結果:

false

true

答案所有繼承自

system.valuetype

的型別都是值型別,而其他型別都是引用型別。值型別的賦值會產生乙個新的資料副本,所以每個值型別都擁有乙個

資料副本,而引用型別的賦值則是賦值引用。值型別的物件分配在堆疊上,而引用型別的物件分配在堆上。當比較兩個值型別時,進行的是內容比較,而比較兩個引

用型別時,進行的是引用比較。

筆者這裡列舉的,僅僅是值型別和引用型別的一些主要區別,通過這些本質區別,可以產生更多的細節區別,有興趣的讀者可以自己總結整理。

值型別和引用型別區別

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

引用型別和值型別區別

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

值型別和引用型別的區別

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