object类型
object 類型
object 類型(System.Object)是所有類型的終極父類。任何類型都可以向上轉(zhuǎn)換為 object 類型。
public class Stack {int position;object[] data = new object[10];public void Push(object obj){data[position++] = obj;}public object Pop(){return data[--position];} }由于 Stack 類的操作對(duì)象是 object,所以實(shí)現(xiàn) Push 和 Pop 任意類型的實(shí)例的操作。
Stack stack = new Stack(); stack.Push ("sausage"); // Upcast string s = (string) stack.Pop(); // Downcast, so explicit cast is needed Console.WriteLine (s); // sausageobject 是引用類型,承載了類的優(yōu)點(diǎn)。但 int 等值類型也可以和 object 類型相互轉(zhuǎn)換并加入棧中。csharp 稱這種特性為類型一致化。
stack.Push (3); int three = (int) stack.Pop();當(dāng)值類型和 object 類型相互轉(zhuǎn)換時(shí),公共語(yǔ)言運(yùn)行時(shí)(CLR)必須進(jìn)行一些特定的工作來(lái)對(duì)接值類型和引用類型在語(yǔ)義上的差異,這個(gè)過(guò)程稱為裝箱(boxing)和拆箱(unboxing)。
1 裝箱和拆箱 Boxing and Unboxing
裝箱
- 裝箱是將值類型實(shí)例轉(zhuǎn)換為引用類型實(shí)例。
- 引用類型可以是 object 類或接口。
🎃 一個(gè)不可空的值類型裝箱之后,其結(jié)果是得到一個(gè)類型的對(duì)象的引用,這里的類型是原式類型裝箱后的一種形態(tài):
int x = 5; object o = x;這里的 o 就是到“裝箱的后 int”的一個(gè)對(duì)象的引用。裝箱后的 int 和 int 在 csharp 中其實(shí)是看不出來(lái)的,即如果調(diào)用 o.GetType() 其結(jié)果和 typeof(int) 是一樣的。
拆箱
-
拆箱與裝箱相反,它把 object 類型轉(zhuǎn)換為原始的值類型。
int y = (int)obj; // Unbox the int -
拆箱需要顯式類型轉(zhuǎn)換。運(yùn)行時(shí)將檢查提供的值類型和真實(shí)的對(duì)象類型是否匹配,并在檢查出錯(cuò)時(shí)拋出 InvalidCastException:
object obj = 9; // 9 is inferred to be of type int long x = (long) obj; // InvalidCastException以下語(yǔ)句是正確的:
object obj = 9; int x = (int)obj; object obj = 3.5; // 3.5 is inferred to be of type double int x = (int)(double)obj; // x is now 3 // (double) 是拆箱操作而 (int) 是數(shù)值轉(zhuǎn)換操作 -
裝箱轉(zhuǎn)換對(duì)系統(tǒng)提供一致性的數(shù)據(jù)類型至關(guān)重要,但該體系不夠完美,數(shù)組和泛型只支持引用轉(zhuǎn)換,不支持裝箱轉(zhuǎn)換。
object[] a1 = new string[3]; // Legal object[] a2 = new int[3]; //Error
裝箱和拆箱的復(fù)制
- 裝箱是把值類型的實(shí)例復(fù)制到一個(gè)新對(duì)象中。
- 拆箱是把對(duì)象的內(nèi)容復(fù)制到一個(gè)新的值類型的實(shí)例。
2 靜態(tài)和運(yùn)行時(shí)類型檢查
csharp 程序在靜態(tài)(編譯時(shí))和運(yùn)行時(shí)(CLR)都會(huì)執(zhí)行類型檢查。
-
靜態(tài)類型檢查使編譯器在程序沒(méi)有運(yùn)行的情況下檢查程序的正確性。例如,因?yàn)榫幾g器會(huì)強(qiáng)制進(jìn)行靜態(tài)類型檢查因而以下代碼會(huì)出錯(cuò):
int x = "5"; -
運(yùn)行時(shí)的類型檢查有 CLR 執(zhí)行,在使用引用類型轉(zhuǎn)換或者拆箱操作進(jìn)行向下類型轉(zhuǎn)換時(shí)發(fā)生:
object y = "5"; int x = (int)y; // Runtime error, downcast failed運(yùn)行時(shí)可以進(jìn)行類型檢查是因?yàn)槎?#xff08;Heap)上的每一個(gè)對(duì)象都在內(nèi)部存儲(chǔ)了類型標(biāo)識(shí),這個(gè)標(biāo)識(shí)可以通過(guò) object 類的 GetType 方法得到。
3 GetType 方法和 typeof 操作符
csharp 所有類型在運(yùn)行時(shí)都以 System.Type 類的實(shí)例表示,兩種基本方法可以獲得 System.Type 對(duì)象:
- 在類型實(shí)例上調(diào)用 GetType 方法。
- 在類型名稱上使用 typeof 操作符。
- GetType 是在運(yùn)行時(shí)被計(jì)算出的。
- typeof 是在編譯時(shí)靜態(tài)計(jì)算出的(如果是使用泛型類型參數(shù),那么它將由即時(shí)編譯器(JIT)解析)。
?? System.Type擁有諸多屬性,例如類型的名稱、程序集、基類型等屬性:
🌴 當(dāng)在值類型上調(diào)用 GetType() 方法時(shí),這個(gè)值類型首先必須裝箱。對(duì)可空值類型來(lái)說(shuō),它要么引起 NullReferenceException 異常,要么返回底層的非可空值類型。
int? noValue = null; Console.WriteLine(noValue.GetType()); // NullReferenceExceptionint? hasValue = new int?(5); Console.WriteLine(hasValue.GetType()); // System.Int324 ToString 方法
ToString 方法返回類型實(shí)例的默認(rèn)文本描述。所有內(nèi)置類型都重寫(xiě)了方法。
int x = 1; string s = x.ToString(); // s is "1"可以使用下面的方法在自定義的類中重寫(xiě) ToString 方法:
public class Panda {public string name;public override string ToString() => name; }Panda p = new Panda {name = "Petey"}; Console.WriteLine(p.ToString()); // Petey如果不重寫(xiě) ToString 方法,將返回類型的名稱。
🍂 當(dāng)直接在值類型對(duì)象上調(diào)用 ToString 這樣的 object 成員時(shí),若改成員是重寫(xiě)的則不會(huì)發(fā)生裝箱。只有進(jìn)行類型轉(zhuǎn)換時(shí)才會(huì)執(zhí)行裝箱操作:
總結(jié)
- 上一篇: sci期刊发表论文注意事项
- 下一篇: 从头发表SCI论文:新手怎么发表第一篇计