在C#中,根據(jù)這些數(shù)據(jù)類型在內(nèi)存中存儲(chǔ)值的方式對(duì)它們進(jìn)行分類。C#包括以下類別的數(shù)據(jù)類型:
值類型
引用類型
指針類型
如果數(shù)據(jù)類型在其自己的內(nèi)存空間中保存數(shù)據(jù)值,則它是一種值類型。這意味著這些數(shù)據(jù)類型的變量直接包含值。
所有值類型都從System.ValueType派生,而System.ValueType又從System.Object派生。
例如,整數(shù)變量 int i = 100;
系統(tǒng)將100存儲(chǔ)在為變量 i 分配的內(nèi)存空間中。下圖說明了如何將100存儲(chǔ)在“i”的內(nèi)存(0x239110)中的某個(gè)假設(shè)位置:
以下數(shù)據(jù)類型均為值類型:
bool
byte
char
decimal
double
enum
float
int
long
sbyte
short
struct
uint
ulong
ushort
當(dāng)您將值類型的變量從一種方法傳遞到另一種方法時(shí),系統(tǒng)會(huì)在另一種方法中創(chuàng)建變量的單獨(dú)副本。如果在一個(gè)方法中更改了值,則不會(huì)影響另一方法中的變量。
static void ChangeValue(int x) { x = 200; Console.WriteLine(x); } static void Main(string[] args) { int i = 100; Console.WriteLine(i); ChangeValue(i); Console.WriteLine(i); }
100
200
100
在上面的示例中,即使在將 Main ()方法中的變量 i 傳遞給 ChangeValue ()方法并更改其值之后,它仍然保持不變。
與值類型不同,引用類型不會(huì)直接存儲(chǔ)其值。相反,它存儲(chǔ)正在存儲(chǔ)值的地址。換句話說,引用類型包含指向另一個(gè)保存數(shù)據(jù)的存儲(chǔ)位置的指針。
例如,以下字符串變量:
string s = "Hello World!!";
下圖顯示了系統(tǒng)如何為上述字符串變量分配內(nèi)存。
如上圖所示,系統(tǒng)為變量s選擇內(nèi)存中的隨機(jī)位置(0x803200)。變量s的值為0x600000,這是實(shí)際數(shù)據(jù)值的內(nèi)存地址。因此,引用類型存儲(chǔ)實(shí)際值所在位置的地址,而不是值本身。
以下是引用類型數(shù)據(jù)類型:
字符串
數(shù)組(即使它們的元素是值類型)
類
委托
當(dāng)您將引用類型變量從一個(gè)方法傳遞到另一個(gè)方法時(shí),它不會(huì)創(chuàng)建新的副本; 相反,它會(huì)傳遞變量的地址。因此,如果我們改變方法中變量的值,它也會(huì)反映在調(diào)用方法中。
static void ChangeReferenceType(Student std2) { std2.StudentName = "Steve"; } static void Main(string[] args) { Student std1 = new Student(); std1.StudentName = "Bill"; ChangeReferenceType(std1); Console.WriteLine(std1.StudentName); }
Steve
在上面的示例中,我們將 Student 對(duì)象 std1 傳遞給ChangeReferenceType()方法。在這里,它實(shí)際上傳遞std1的內(nèi)存地址。因此,當(dāng)ChangeReferenceType()方法更改StudentName時(shí),它實(shí)際上是在更改std1對(duì)象的StudentName,因?yàn)閟td1和std2都指向內(nèi)存中的同一地址。
引用類型變量的默認(rèn)值null是未初始化時(shí)。 Null表示不引用任何對(duì)象。
值類型變量不能為null,因?yàn)樗4嬷刀皇莾?nèi)存地址。C#2.0引入了可為空的類型,使用它可以為值類型變量分配null或聲明值類型變量而無需為其分配值。