1. 程式人生 > >C#base和this的區別

C#base和this的區別

沒有 .net images ins name lan .cn 基礎上 tps

轉自(https://www.cnblogs.com/reommmm/archive/2009/03/23/1419573.html)

new關鍵字引起了大家的不少關註,尤其感謝Anders Liu的補充,讓我感覺博客園賦予的交流平臺真的無所不在。所以,我們就有必要繼續這個話題,把我認為最值得關註的關鍵字開展下去,本文的重點是訪問關鍵字(Access Keywords):base和this。雖然訪問關鍵字不是很難理解的話題,我們還是有可以深入討論的地方來理清思路。還是老辦法,我的問題先列出來,您是否做好了準備。

  ? 是否可以在靜態方法中使用base和this,為什麽?

  ? base常用於哪些方面?this常用於哪些方面?

  ? 可以base訪問基類的一切成員嗎?

  ? 如果有三層或者更多繼承,那麽最下級派生類的base指向那一層呢?例如.NET體系中,如果以base訪問,則應該是直接父類實例呢,還是最高層類實例呢?

  ? 以base和this應用於構造函數時,繼承類對象實例化的執行順序如何?

  2. 基本概念

  base和this在C#中被歸於訪問關鍵字,顧名思義,就是用於實現繼承機制的訪問操作,來滿足對對象成員的訪問,從而為多態機制提供更加靈活的處理方式。

  2.1 base關鍵字

  其用於在派生類中實現對基類公有或者受保護成員的訪問,但是只局限在構造函數、實例方法和實例屬性訪問器中,MSDN中小結的具體功能包括:

  ? 調用基類上已被其他方法重寫的方法。

  ? 指定創建派生類實例時應調用的基類構造函數。

  2.2 this關鍵字

  其用於引用類的當前實例,也包括繼承而來的方法,通常可以隱藏this,MSDN中的小結功能主要包括:

  ? 限定被相似的名稱隱藏的成員

  ? 將對象作為參數傳遞到其他方法

  ? 聲明索引器

  3. 深入淺出

  3.1 示例為上

  下面以一個小示例來綜合的說明,base和this在訪問操作中的應用,從而對其有個概要了解,更詳細的規則和深入我們接著闡述。本示例沒有完全的設計概念,主要用來闡述base和this關鍵字的使用要點和難點闡述,具體的如下:

技術分享圖片
using
System; namespace Anytao.net.My_Must_net { public class Action { public static void ToRun(Vehicle vehicle) { Console.WriteLine("{0} is running.", vehicle.ToString()); } } public class Vehicle { private string name; private int speed; private string[] array = new string[10]; public Vehicle() { } //限定被相似的名稱隱藏的成員 public Vehicle(string name, int speed) { this.name = name; this.speed = speed; } public virtual void ShowResult() { Console.WriteLine("The top speed of {0} is {1}.", name, speed); } public void Run() { //傳遞當前實例參數 Action.ToRun(this); } //聲明索引器,必須為this,這樣就可以像數組一樣來索引對象 public string this[int param] { get{return array[param];} set{array[param] = value;} } } public class Car: Vehicle { //派生類和基類通信,以base實現,基類首先被調用 //指定創建派生類實例時應調用的基類構造函數 public Car() : base("Car", 200) { } public Car(string name, int speed) : this() { } public override void ShowResult() { //調用基類上已被其他方法重寫的方法 base.ShowResult(); Console.WriteLine("It‘s a car‘s result."); } } public class Audi : Car { public Audi() : base("Audi", 300) { } public Audi(string name, int speed) : this() { } public override void ShowResult() { //由三層繼承可以看出,base只能繼承其直接基類成員 base.ShowResult(); base.Run(); Console.WriteLine("It‘s audi‘s result."); } } public class BaseThisTester { public static void Main(string[] args) { Audi audi = new Audi(); audi[1] = "A6"; audi[2] = "A8"; Console.WriteLine(audi[1]); audi.Run(); audi.ShowResult(); } } }
base和this示例

3.2 示例說明

  上面的示例基本包括了base和this使用的所有基本功能演示,具體的說明可以從註釋中得到解釋,下面的說明是對註釋的進一步闡述和補充,來說明在應用方面的幾個要點:

  ? base常用於,在派生類對象初始化時和基類進行通信。

  ? base可以訪問基類的公有成員和受保護成員,私有成員是不可訪問的。

  ? this指代類對象本身,用於訪問本類的所有常量、字段、屬性和方法成員,而且不管訪問元素是任何訪問級別。因為,this僅僅局限於對象內部,對象外部是無法看到的,這就是this的基本思想。另外,靜態成員不是對象的一部分,因此不能在靜態方法中引用this。

  ? 在多層繼承中,base可以指向的父類的方法有兩種情況:一是有重載存在的情況下,base將指向直接繼承的父類成員的方法,例如Audi類中的ShowResult方法中,使用base訪問的將是Car.ShowResult()方法,而不能訪問Vehicle.ShowResult()方法;而是沒有重載存在的情況下,base可以指向任何上級父類的公有或者受保護方法,例如Audi類中,可以使用base訪問基類Vehicle.Run()方法。這些我們可以使用ILDasm.exe,從IL代碼中得到答案。

技術分享圖片
.method public hidebysig virtual instance void 

ShowResult() cil managed

{

// 代碼大小       27 (0x1b)

  .maxstack  8

IL_0000:  nop

IL_0001:  ldarg.0

//base調用父類成員

  IL_0002:  call       instance void Anytao.net.My_Must_net.Car::ShowResult()

IL_0007:  nop

IL_0008:  ldarg.0

//base調用父類成員,因為沒有實現Car.Run(),所以指向更高級父類

  IL_0009:  call       instance void Anytao.net.My_Must_net.Vehicle::Run()

IL_000e:  nop

IL_000f:  ldstr      "It‘s audi‘s result."

IL_0014:  call       void [mscorlib]System.Console::WriteLine(string)

IL_0019:  nop

IL_001a:  ret

} // end of method Audi::ShowResult
IL代碼

3.3 深入剖析

  如果有三次或者更多繼承,那麽最下級派生類的base指向那一層呢?例如.NET體系中,如果以base訪問,則應該是直接父類實例呢,還是最高層類實例呢?

  首先我們有必要了解類創建過程中的實例化順序,才能進一步了解base機制的詳細執行過程。一般來說,實例化過程首先要先實例化其基類,並且依此類推,一直到實例化System.Object為止。因此,類實例化,總是從調用System.Object.Object()開始。因此示例中的類Audi的實例化過程大概可以小結為以下順序執行,詳細可以參考示例代碼分析。

  ? 執行System.Object.Object();

  ? 執行Vehicle.Vehicle(string name, int speed);

  ? 執行Car.Car();

  ? 執行Car.Car(string name, int speed);

  ? 執行Audi.Audi();

  ? 執行Audi.Audi(string name, int speed)。

  我們在充分了解其實例化順序的基礎上就可以順利的把握base和this在作用於構造函數時的執行情況,並進一步了解其基本功能細節。

  下面更重要的分析則是,以ILDASM.exe工具為基礎來分析IL反編譯代碼,以便更深層次的了解執行在base和this背後的應用實質,只有這樣我們才能說對技術有了基本的剖析。

Main方法的執行情況為:

技術分享圖片
IL分析base和this執行

因此,對重寫父類方法,最終指向了最高級父類的方法成員。

  4. 通用規則

  ? 盡量少用或者不用base和this。除了決議子類的名稱沖突和在一個構造函數中調用其他的構造函數之外,base和this的使用容易引起不必要的結果。

  ? 在靜態成員中使用base和this都是不允許的。原因是,base和this訪問的都是類的實例,也就是對象,而靜態成員只能由類來訪問,不能由對象來訪問。

  ? base是為了實現多態而設計的。

  ? 使用this或base關鍵字只能指定一個構造函數,也就是說不可同時將this和base作用在一個構造函數上。

  ? 簡單的來說,base用於在派生類中訪問重寫的基類成員;而this用於訪問本類的成員,當然也包括繼承而來公有和保護成員。

  ? 除了base,訪問基類成員的另外一種方式是:顯示的類型轉換來實現。只是該方法不能為靜態方法。

C#base和this的區別