初讀CLR Via C# 之類型基礎(一)

來源:互聯網
上載者:User

     最近由於出差在外地,再加上自己在學習一些新的知識,所以遲遲沒有再看這本書,更沒有更新此系列的後續內容,但是這本書確實是本好書,不想就此放下,碰巧今天也比較悠閑,於是今天又一次回顧了之前的內容,並開始了新的閱讀。今天開始盡量儘快進行更新。

     在開始之前,我想先講一下繼承的概念。大家都知道,物件導向是由:封裝、繼承、多態來體現的,至於什麼是封裝,不是很明白的朋友請去Google找下答案吧。那麼,什麼事繼承?“繼承”我們可以理解為是一種在無需重新編寫類本身的情況下,對該類進行擴充的能力,並且可以使用現有類的所有功能。那麼,通過繼承建立的新類,我們可以稱之為:“子類”或者“衍生類別”,反之,被繼承的類我們稱之為:“父類”或者“基類”,子類可以繼承多個父類(衍生類別可以繼承多個基類)但是一般情況下,一個子類只能有一個父類,要實現多重繼承,可以通過多級繼承來實現。繼承的概念,筆者就先簡單的介紹到這裡吧,如果還是有些不明白的讀者,可以在網上找些資料,相信部落格園裡面也有對繼承概念有專門講解的博文。

    在我們C#或者JAVA中,不管我們自己建立、調用任何一個類,它的頂級父類只有System.Object這一個類。也就是說,所有的類都是通過它進行衍生的。在我們建立完一個類的時候,類裡面任何方法、欄位、屬性都不去寫,在另一個類中進行執行個體化之後,都會看到一些方法如:Equals();GetHashCode();ToString();GetType()等。那麼這些方法就是System.Object類中的方法。這就是一個繼承的概念,在我們建立一個類的時候,它繼承了System.Object類、擁有了System.Object類中的方法,並且對System.Object類進行了一個擴充。上面我提到一個執行個體化。我們都是用new關鍵字來對一個類進行執行個體化(非靜態類(static))在我們new了一個執行個體化的時候,會自動在堆上為我們建立一個“類型對象指標”和“同步索引快”,而且CLR會自動給我們分配一個該類所需要的記憶體,這個記憶體的大小根據類中的欄位所需要的位元組數進行設定,然而,最終new關鍵字會調用System.Object的建構函式,並進行返回,會返回給新對象一個引用(對象指標),我們所有調用類中的方法,屬性的時候,是根據這個引用的記憶體位址進行操作的。也可以理解為我們操作記憶體(實際上是CLR幫我們完成的),到這裡可能會有一個問題,就是,這個對象的記憶體我們 如何去釋放。這就輪到我們CLR的記憶體回收機制(GC)進行檢測,並對不再訪問的記憶體進行自動釋放操作。記憶體回收機制將在基本內容更新過以後進行更新。

   在我們日常的使用中,會非常頻繁用到類型的轉換。那麼類型是可以隨便進行轉換的麼(比如Person類型轉換成DateTime類型)?答案是不可以。可是為什麼不可以?首先,CLR最重要的特性之一就是安全性。這個安全性就已經把我們限制死了。在我們使用反射的時候會用到GetType()方法,這個方法是一個非虛方法,是不可重寫的方法,這個方法不可重寫,就意味著我們不能把Person類通過GetType方法偽裝成DateTime類型,並進行返回。在類型轉換的時候,CLR准許我們將一個父類強制轉換成它的子類,而不需要任何特殊的文法把子類轉換成父類,例如:

namespace Chapter4
{
class Program
{
static void Main(string[] args)
{
//子類轉換成父類不需要強制轉換
Object o = new Person();
//父類轉換成子類必須進行強制類型轉換
Person p = (Person)o;

}
}

//該類繼承自System.Object類
internal class Person
{
private string name;
private int age;
}
}

那麼兩個類都整合自Object類,為什麼就不能相互進行轉換?CLR在每次進行轉換的時候,都會對轉換的對象進行檢查,確定o是否引用自Peron對象,或者是否是從Peron類派生 的任何子類,如果是CLR將准許轉換,否則將拋出異常,就拿剛才說的Peron轉換成DateTime為例,代碼如下:

 class Program
{
static void Main(string[] args)
{
//子類轉換成父類不需要強制轉換
Object o = new Person();
//父類轉換成子類必須進行強制類型轉換
Person p = (Person)o;
//將Person的子類轉換成Person
Man m = new Man();
MagicPerson(m);
//構建一個DateTime對象,並轉換成Person
DateTime dtNow = DateTime.Now;
MagicPerson(dtNow);

}

private static void MagicPerson(object o)
{
Person p = (Person)o;
}
}

//該類繼承自System.Object類
internal class Person
{
private string name;
private int age;
}
//該類繼承自Person(最高基類為System.Object)
internal class Man : Person
{
private string sex;
}

以上的代碼完全可以通過編譯,並運行。那麼第二次運行到MagicPerson方法的時候,CLR會給我們拋除一個為:System.InvalidCastExiception異常,並告訴我們轉換失敗。為什麼會轉換失敗?我們來分析一下CLR進行類型轉換時候的工作步驟。首先在編譯時間,編譯器並不知道MagicPerson中參數o到底是誰的引用,所以編譯器准許代碼編譯通過。但在運行時,CLR知道了第一次進來的o是Man的引用,並繼承自Person類,第一次轉換成功。當再次進入MagicPerson方法的時候對象的引用為DateTime的引用。CLR會核實DateTime類型是否繼承自Person或者是否是Peron類型,發現並不繼承自Person類也是Person類型,便拋出異常資訊終止轉型。
     在以上的代碼例子中,MagicPerson方法在實際運用中參數應該設定為Person類型,這樣的話,編譯器就會報錯,在造成更大損失之前,把罪惡的種子掐死在搖籃之中。

     先去吃飯,吃飯回來之後接著更新。

   

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.