1. 程式人生 > >C#本質論6.0第五章:類

C#本質論6.0第五章:類

得到 結束 管理 多個實例 局部變量 理解 管理器 靜態方法 修改

面向對象編程

封裝:

封裝的目的是隱藏細節。在必要的時候,細節仍然可以訪問,但通過巧妙的封裝細節,大的程序變得更容易理解,數據不會因為不慎而被修改,代碼也變得更容易維護。

繼承:

繼承允許在這些相似但又不同的物體之間建立“屬於”關系從而得到一個類層次結構。更具體的類型稱為派生類型或者子類型,更常規的類型稱為基類型或者超類型

多態性:

多態性意味著一個方法或類型可以具有多種形式的表現。在多態性的幫助下,不同的類型能自己照料一個方法的實現細節,因為共享同一個公共基類型(或接口)的多個派生類型也包含了相同的方法簽名。

訪問修飾符:

訪問修飾符的作用是提供封裝,標識所修飾成員的封裝級別。

字段

在類中存儲數據的變量稱為成員變量,更標註的為字段,它是與包容類型關聯的具名存儲單元,實例字段是在類的級別上聲明的變量,用於存儲與對象關聯的數據。

屬性

class Employee
{
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
        }
    }
    private string _FirstName;
}

依然可以使用簡單的賦值操作符對屬性進行賦值,屬性的定義使用了三個上下文關鍵字:get,setvalue

  • C#3.0支持自動實現的屬性:允許在聲明屬性時,不添加取值或賦值方法,也不聲明任何支持字段,一切都將自動實現。
public string Title{ get; set; }
  • 在C#6.0中,可以類似於初始化字段實現初始化屬性:
public string Salary { get; set; } = "Not Enough";

屬性的內部工作機制:待補

構造器

構造器是“運行時”用來初始化對象實例的方法。

  • new操作符返回一個引用,它指向實例化好的對象。new操作符從內存管理器獲取“空白”內存,調用指定的構造器,將對“空白”內存的引用作為隱式的this參數傳給構造器。構造器鏈剩余的部分開始執行,在構造器之間傳遞引用。這些構造器都沒有返回類型。構造器鏈上的執行結束後,new操作符返回內存引用。現在,該引用指向的內存處於初始化好的形式。

  • 又在聲明中又在構造器內部進行賦值的情況下,只要在聲明時賦值發生之後,構造器內部的賦值才會發生,最終生效的是構造器內部的賦值,它會覆蓋聲明時的賦值。

默認構造器:

沒有顯式定義的構造器,該構造器不獲取參數,稱為默認構造器。

對象初始化器:

class Program
{
    static void Main()
    {
        Employee employee1 = new Employee("Inigo","Montoga")
        {
            Title = "Computer Nerd",
            Salary = "Not enough"
        };
    }
}

集合初始化器:

class Program
{
    static void Main()
    {
        List<Employee> employees = new List<Employee>()
        {
            new Employee("Inigo","Montoya"),
            new Employee("Kevin","Bost")
        };
    }
}

終結器:

終結器是在對象被判定“不可達”之後的不確定時間內執行,垃圾回收器會在一次垃圾回收過程中識別出帶有終結器的對象。但不是立即回收這些對象,而是將它們添加到一個終結隊列中。一個獨立的線程遍歷終結隊列中的每一個對象,調用其終結器,然後將其從隊列中刪除,使其再次可供垃圾回收器處理。

構造器的重載:

可同時存在多個構造器,只要參數的數量和類型有區別。

構造器鏈:

在一個冒號後面添加this關鍵字,再添加被調用構造器的參數列表。

class Employee
{
    public Employee(string firstName,string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
    public Employee(int id,string firstName,string lastName):this(firstName,lastName)
    {
        Id = id;
    }
    public Employee(int id)
    {
        Id = id;
    }
    //...
}

匿名類型:

它們是由編譯器動態生成的數據類型,而不是通過顯式的類定義來聲明的。編譯器遇到匿名類型的語法時,會自動生成一個CIL類,該類具有與匿名屬性聲明中的已經命名的值和數據類型對應的屬性。該類型為靜態類型,具有完全的可訪問性。

雖然編譯器支持匿名類型聲明,但除非使用Lambda表達式和查詢表達式關聯來自不同類型的數據,或者對數據進行水平投射,否則一般情況下還是應該盡量避免使用這樣的聲明,甚至避免使用var來指定隱式類型的變量,除非需要頻繁查詢集合中的數據而使顯式的類型聲明成為負擔,否則最好還是顯式地聲明類型。

靜態成員:

靜態字段:

為了定義能由多個實例共享的數據,需要使用static關鍵字。包含static修飾符的字段稱為靜態字段

實例字段,也就是非靜態字段,可以在聲明的同時進行初始化。

未初始化的靜態字段將獲得默認值(0,null,false)等,即default(T)的結果。所以即使沒有顯式賦值的靜態字段也可以被訪問。

非靜態字段針對它們從屬的每個對象,都提供一個新的存儲位置。

靜態方法:

直接在類名之後訪問靜態方法,訪問這種方法不需要有實例,所以this關鍵字在靜態方法中無效。除此之外,要在靜態方法內部直接訪問實例字段或實例方法,必須先獲得對字段或方法所從屬於的那個特定的實例的引用。

靜態構造器:

用於對類進行初始化。靜態構造器不支持顯式調用,而是運行時在首次訪問類時自動調用靜態構造器,使用靜態構造器將類中的靜態數據初始化特定的值,尤其是無法通過聲明的一次簡單賦值來獲得初始值的時候。

  • 在靜態構造器中進行的賦值,將優先於聲明的賦值。
  • 不要在靜態構造器中引發異常,這會造成類型在應用程序剩余的生存期中無法使用。

靜態屬性:

相較於公共靜態字段來說,提供了一定程度的封裝。

靜態類:

不包含任何實例字段,用static關鍵字修飾該類,防止該類被實例化,同時防止在類的內部聲明任何實例字段或方法。

不能從靜態類派生出其他類。

拓展方法:

能模擬為不同的類創建實例方法只需更改靜態方法的簽名,使第一個參數成為要拓展的類型,並在類型名稱前面附加this關鍵字。

public static void CopyTo(
    this DirectoryInfo sourceDirectory, string target, SearchOption option, string searchPattern)
{
    //...
}
  • 第一個參數是要拓展或者要操作的類型,這稱為“被拓展的類型”。
  • 為了指定拓展方法,要在被拓展類型名稱前面附加this修飾符。
  • 要將方法作為拓展方法來訪問,要用using指定導入拓展類型的命名空間,或者使拓展類型和調用代碼在同一個命名空間裏。

封裝數據:

  • const關鍵字:const字段包含在編譯時確定的值,它不可以在運行時改變。常量字段自動成為靜態字段,但是將常量字段顯式聲明為static會造成編譯錯誤。常量字段通常只使用包括包含字面量的類型。
  • readonly關鍵字:readonly字段修飾符只能用於字段,不能用於局部變量,它指出字段值只能從構造器中更改,或者在聲明時通過初始化器修改。可以在執行時為readonly字段賦值,由於readonly字段必須從構造器中設置,所以編譯器要求這種字段能從其屬性外部訪問。另外,readonly字段不限於包含字面量的類型。

嵌套類:

假如一個類在它的包容類外部沒有多大意義,就適合將其設計成嵌套類。

  • 嵌套類中的this成員代表嵌套類而不是包容類的實例,若想訪問包容類的實例,一個方法是顯式傳遞包容類的實例。
  • 嵌套類能訪問包容類的任何成員,包括私有成員,反之則不行。

分部類:

分部類是一個類的多個部分,這些部分可以合並成一個完整的類。

//File: Program1.cs
partial class Program
{ 
}
//File: Program2.cs
partial class Program
{
}

分部方法:(待補)

分部方法使生成的代碼能調用並非一定要實現的方法。

C#本質論6.0第五章:類