.net框架读书笔记---基础类型
接上一篇.net框架讀書筆記---值類型的裝箱與拆箱,
一、Object
CLR要求每個類型都最終集成自System.Object類型,這意味著以下兩種定義是相同的:
?
//隱式繼承自Objectclass Employee
{
//...
}
//顯示繼承Object
class Employee : System.Object
{
//...
}
CLR要求所有的對象都要用new操作符來創建。下面的語句展示了怎樣創建一個Employee對象:
?
Employee e = new Employee("para");下面是new操作符所執行的工作:
- 從托管堆(managed heap)中分配指定類型所需數量的字節來作為存儲其對象的內存空間。
- 初始化對象的附加成員。內一個對象實例都有兩個附加成員。其中第一個成員指向類型方法表的指針,第二個成員為SyncBlockIndex(CLR使用該字段進行線程同步控制),CLR使用這兩個成員來管理對象的實例。
- 傳入new操作符中指定的參數(上面例子為“para”),調用類型的實例構造器;
在new完成所有這些操作后,它將返回一個指向新創建對象的引用。在上面例子中,該引用被保存在變量e中,其類型為Employee。沒有和new對應的delete操作符,在CLR中,我們無法顯式釋放對象所占用的內存,CLR引入一種垃圾收集環境來自動檢測那些不再被使用或訪問的對象,并自動釋放他們的內存。
二、類型轉換
CLR最重要的一個特性就是類型安全。CLR在運行時總能知道一個對象的類型。也可以通過調用GetType方法來得到對象的準確類型。CLR允許我們將對象轉換為其原來的類型或者它的任何一個基類型,C#不需要任何特殊的語法就可以將對象轉換為其任何一個基類型,因為轉化為基類型被認為是安全的隱式操作,然而將對象轉換為它的任何派生類時,C#要求進行顯式轉型,因為這樣的轉型有可能會失敗。下面代碼演示了我如何將對象轉換為它的基類型和派生類型:、
?
代碼 class Program{
static void Main(string[] args)
{
//這里不需要轉型,因為new返回的是一個Employee對象。
//而object是Employee的基類型
object o = new Employee();
//這里需要轉型,因為Employee繼承自object
Employee e = (Employee)o;
Employee e1 = o;//這樣子編譯是通不過去的
}
}
class Employee
{
//...
}
上面的例子顯示了要是代碼通過編譯我們需要做的一些事情,下面解釋運行時發生的行為。在運行時,CLR會檢查轉型操作以確保總是將對象轉型它的實際類型或者它的任何基類型。下面的代碼能夠通過編譯,但是在運行時會拋出InvalidCastException異常:
?
代碼 class Employee{
//...
}
class Manager : Employee
{
//...
}
class Program
{
static void Main(string[] args)
{
//構造一個Manager對象并將其傳遞給PromoteEmployee。
//一個Manager“IS -A”Employee,PromoteEmployee將正常運行
Manager m = new Manager();
PromoteEmployee(m);
//構造一個DateTime對象并將其傳遞給PromoteEmployee。
//由于DateTime并非繼承自Employee,PromoteEmployee將會報錯
DateTime newYears = new DateTime(2001, 1, 1);
PromoteEmployee(newYears);
}
public static void PromoteEmployee(object o)
{
//這里,編譯器不知道對象o引用的實際類型。
//所以編譯器允許代碼通過編譯。然而,在實際運行時,
//CLR會獲知o引用的類型(每當進行類型轉換操作時),
//并且會檢查對象是否為Employee,或者任何繼承自Employee類型
Employee e = (Employee)o;
}
}
在Main方法中,我們首先構造了一個Manager對象,并將其傳遞給PromoteEmployee。這段代碼會成功編譯并執行,因為Manager繼承自Object,而object正是PromoteEmployee期望的參數類型。一旦進入PromoteEmployee內部,CLR將確認o引用的對象或者是一個Employee,或者繼承自Employee的一個類型。因為Manager繼承自Employee,所以CLR將成功執行轉型操作,并允許PeomoteEmployee繼續執行。
在PromoteEmployee返回之后,Main又構造了一個DateTime對象并將其傳遞給PromoteEmployee。同樣DateTime也繼承自Object,所以PromoteEmployee將會編譯通過。但是在PromoteEmployee內部,CLR會檢查轉型操作,并將檢測出o引用對象為DateTime類型,而不是Employee或者任何繼承自Employee的類型。這時,CLR將禁止執行轉型操作,并拋出InvalidCastException異常。
如果CLR允許這樣的轉型操作,代碼也就失去了類型安全,結果將變得不可預期,類型安全是.net框架中非常重要的一個部分。
三、使用is和as操作符轉型
C#提供了一種利用is操作符進行轉型的方式。它檢查對象是否和給定的類型兼容,并返回判斷結果:true或者false。另外,is操作符永遠不會拋出異常。下面為is操作符的典型使用方法:
?
if (o is Employee){
Employee e = (Employee)o;
}
在上面的代碼中,CLR實際上會對對象的類型檢查了兩次:is操作符首先檢查o所引用的對象是否和Employee類型兼容。如果兼容,在if語句內,CLR在執行轉型時又會檢查o事都為一個Employee引用。由于這種編程范式十分常見,C#便為我們提供一種新的轉型方式,即as操作符,它可以簡化代碼的同時提高性能,看下面代碼:
?
Employee e = o as Employee;if (e != null)
{
///.......
}
在上面的代碼中,CLR會檢查o所引用的對象是否和Employee兼容。如果兼容,as返回一個指向同一個對象的非空指針。如果不兼容,as返回null。注意as操作符執行過程中,CLR只檢查了一次對象的類型。效率高
總結
以上是生活随笔為你收集整理的.net框架读书笔记---基础类型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Kosaraju算法(发现强连通分图算法
- 下一篇: APC UPS报错一例