CSharp初級篇 1-4 this、索引器、靜態、常量以及只讀

WarrenRyan發表於2019-07-20

.NET Core CSharp初級篇 1-4

本節內容為this、索引器、靜態、常量以及只讀

簡介

在之前的課程中,我們談論過了靜態函式和欄位的一小部分知識,本節內容中,我們將詳細的講解關於物件操作的例子,以及更加深入的解釋物件導向。

常量

常量,顧名思義,就是一直為同一個值的變數,並且值不可以被改變。在C#中,定義一個常量需要使用const關鍵字宣告。常量並不佔用記憶體的空間。在C#程式編譯的時候,編譯器會把任何使用了該常量替換成這個值。

因為常量並不儲存在記憶體中,因此常量只允許使用內建的數值型別,例如:bool、char、string、enum。並且宣告的同時必須對常量進行初始化。

例如我們應用的版本號,通常在應用編譯完成之後都是以一個常量存在,也不需要對他進行操作。看下列程式碼。

public const string Version="v2.1.1"

public string getString(string msg)
{
    return "Copyright@2019" + msg + Version;
}

上述函式程式碼在編譯時,將會變成:

public string getString(string msg)
{
    return "Copyright@2019" + msg + "V2.1.1";
}

因為常量的上述特性,如果Y程式集使用了X程式集中的這個Version常量,如果X修改了該常量為“2.1.2”並重新編譯,若Y不重新編譯,Y中常量還是“2.1.1”,因為該常量會被直接固化於Y中並用常量值替換變數名。因此需要y進行重新編譯才會使用新的常量值。

靜態

靜態是一個很常用的語法,我們可以在類中構造各種靜態成員,例如靜態欄位、函式等等。再C#中定義靜態成員的方法是使用修飾符static,呼叫的時候只需要使用“類名.成員名”。

在之前的課程中,我順帶提過一次,靜態是一個只初始化執行一次,屬於全體共有的一個東西,也可以說是該靜態成員屬於類本體所有,而不是每一個物件所有。我們就從靜態建構函式、靜態欄位、靜態函式這三塊進行一個詳細的講解。

靜態建構函式

我們之前以及對建構函式進行過一個簡單的介紹,建構函式是在類被初始化(例項化)的時候呼叫,並且每建立一個物件就會呼叫一次建構函式。

而靜態建構函式是每一個型別執行一次,也就是這個型別的所有物件公用一個靜態建構函式。這區別與普通建構函式的一個物件執行一次。並且對於靜態建構函式而言,一個類只允許有一個靜態建構函式,並且必須無參。

靜態建構函式在你訪問一個型別的靜態成員的時候,或者例項化一個型別的時候,編譯器會自動的呼叫靜態建構函式。

特別的,因為該初始化的建構函式(靜態建構函式)屬於所有變數共有並且會呼叫,那麼假設該建構函式報錯,那麼這個類將再程式剩餘生命週期內無法再被使用。

靜態欄位

靜態欄位也是一樣,屬於一切成員公有,在任何地方你都可以不例項化類的情況下對靜態欄位操作。

對於靜態欄位的初始化,分為兩種情況:

  • 假定類存在一個靜態建構函式,那麼靜態欄位在靜態建構函式被呼叫的一瞬間就會初始化;
  • 假定不存在靜態建構函式,那麼靜態欄位將會被型別被使用之前的一瞬間初始化(最晚執行),或者更早,在執行時的某一時間(並無法確定)被初始化。

靜態欄位初始化的順序則與定義時的順序一致,例如:

class A
{
    public static int X = Y;
    public static int Y = 15;
}
.....
Console.WriteLine("X:{0},Y:{1}",X,Y)

上例中,X,Y的初始化順序是X先被初始化,此時Y沒有初始化,則是0,因此輸出是X:0,Y:15。

靜態函式

與之前一樣,靜態函式可以在不例項化類的情況下呼叫,但是注意,在靜態函式中,不允許使用任何非靜態的欄位。呼叫的時候直接使用類名.函式名()即可。

靜態類

如果一個類,被宣告為靜態類,那麼該類不可以被例項化,也不可以被繼承,同時不可以包含非靜態成員。非靜態類中,可以包含靜態成員。

只讀

只讀用於欄位的訪問控制,使用readonly關鍵字,通常情況下也可以使用無set訪問器的屬性進行實現。

class A
{
    public string test{get;}
    public readonly string _test;
}

靜態成員的生命週期

從程式開始初始化到程式結束,因此濫用靜態會導致效能問題。

this關鍵字

在C#中,this關鍵字表示操作的當前物件,在類裡面,如果你使用this關鍵字,則this指代的是你每次操作物件時的當前物件。特別的,如果你的函式形參名稱和欄位名相同,並且你需要同時操作這個兩個變數,那麼你需要使用this關鍵字去指明你的操作物件,例如:

class A
{
    private string data;
    public string Data{get{return data;}}

    public void SetData(string data)
    {
        //this.data表示是當前物件的欄位data
        this.data = data;
    }


}

索引器

在之前的陣列操作中,相信大家都發現了陣列的訪問通過了一箇中括號和下標的方式進行訪問,這個東西我們稱為索引器。但是在類中的索引器可以以任何型別作為索引的key,這使得整個類的擴充性變得很好。

如何去定義一個索引器呢?這裡就需要用到我們的this關鍵字了。定義的方式有點類似我們對於屬性的定義

public class A
{
    public double[] arry{get;set;}
    public double this [int index]
    {
        get
        {
            return arry[index];
        }
        set
        {
            arry[index] = value;
        }
    }
}

通過索引器,我們可以自己定義各種不同的索引方式,而不用拘泥於下標訪問

習題

1.請問下列程式碼輸出什麼?為什麼?

class A
{
    public static A a = new A();
    public static int X = 3();
    A()
    {
        Console.WriteLine(X);
    }
}
class Program
{
    static void Main()
    {
        Console.WriteLine(A.X);
    }
}

2.試著使用索引器,寫出一個二維陣列的索引訪問,要求實現倒序訪問(即a[0]訪問最後一位)

前往Github獲取更多本節資料(PPT,例項程式碼)
如果我的教程幫到了您,希望您動動小手,在GitHub給我一個star

Github

BiliBili主頁

WarrenRyan's Blog

部落格園

相關文章