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...