c#學習筆記Day2
第二章
1.屬性
自動實現的屬性:如果屬性的get和set訪問器中沒有任何邏輯,就可以使用自動實現的屬性。這種屬性會自動實現後備成員變數。例如Public int Age{get;set},不需要宣告private int age,編譯器會自動建立他。
使用自動實現的屬性,就不能再屬性設定中驗證屬性的有效性。
2.建構函式
建構函式沒有返回型別。
一般情況下,如果沒有提供任何建構函式,編譯器會在後臺建立一個預設的建構函式。這是一個非常基本的建構函式,他只能把所有的成員欄位初始化為標準的預設值。例如引用型別為空引用,資料型別為0,bool為false。
public class Student
{
private int ID;
private Student(int ID)
{
this.ID = ID;
}
}
這個例子沒有為Student定義任何公有的或受保護的建構函式。這就使Student不能使用new運算子在外部程式碼中例項化(但可以在Student中編寫一個公有靜態屬性或方法,以例項化該類)。這在以下兩種情況下是有用的:
1.類僅用作某些靜態成員或屬性的容器,因此永遠不會例項化他。
2.希望類僅通過呼叫某個靜態成員函式來例項化(這就是所謂物件例項化的類工廠方法)。(這是什麼意思??)
注:
第二種情況,使用靜態成員來例項化。這裡有一個非常常用的模式,即單例模式。
public class TestClass{ private TestClass(){} private static TestClass _instance=null; public static TestClass Instance{ get{ if(_instance==null) _instance=new TestClass(); return _instance; } } public void Method(); } TestClass.Instance.Method();
上面的方式使用私有建構函式確保類只能在獲取靜態成員Instance中例項化,而且上面的程式碼保證了這個類只能被例項化一次,所以稱為單例模式。
3.靜態建構函式
C#的一個新特徵也是可以給類編寫無引數的靜態建構函式。這種建構函式只執行一次。
編寫靜態建構函式的一個原因是,類有一些靜態欄位或屬性,需要在第一次使用類之前,從外部資源中初始化這些靜態欄位和屬性。
轉載:https://www.cnblogs.com/jiagoushi/p/3775046.html
靜態建構函式有哪些特點呢:
- 靜態建構函式沒有修飾符修飾(public,private),因為靜態建構函式不是我們程式設計師呼叫的,是由.net 框架在合適的時機呼叫的。
- 靜態建構函式沒有引數,因為框架不可能知道我們需要在函式中新增什麼引數,所以規定不能使用引數。
- 靜態建構函式前面必須是static 關鍵字。如果不加這個關鍵字,那就是普通的構造函數了。
- 靜態建構函式中不能例項化例項變數。(變數可以分為類級別和例項級別的變數,其中類級別的有static關鍵字修飾)。
- 靜態函式的呼叫時機,是在類被例項化或者靜態成員被呼叫的時候進行呼叫,並且是由.net框架來呼叫靜態建構函式來初始化靜態成員變數。
- 一個類中只能有一個靜態建構函式。
- 無引數的靜態建構函式和無引數的建構函式是可以並存的。因為他們一個屬於類級別,一個屬於例項級別,並不衝突。
- 靜態建構函式只會被執行一次。並且是在特點5中的呼叫時機中進行呼叫。
- 就像如果沒有在類中寫建構函式,那麼框架會為我們生成一個建構函式,那麼如果我們在類中定義了靜態變數,但是又沒有定義靜態建構函式,那麼框架也會幫助我們來生成一個靜態建構函式來讓框架自身來呼叫。
例:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(A.strText);
Console.WriteLine(B.strText);
Console.Read();
}
}
public class A
{
public static string strText;
public string Text;
static A()
{
strText = "AAA";
}
public A()
{
Text = "AAAAAAAAAAAAAAAAAAAAAAAAAA";
}
}
public class B : A
{
static B()
{
strText = "BBB";
}
public B()
{
Text = "BBBBBBBBBBBBBBBBB";
}
}
輸出結果均為:AAA
我們來分析一下出現這個情況的原因所在,當顯示A.strText的時候,因為strText是靜態變數,所以框架會呼叫A的靜態建構函式,此時strText的值為AAA.正確
當顯示B.strText的時候,因為B繼承自A,所以會首先呼叫A的靜態建構函式,但是因為靜態建構函式只會呼叫一次,所以不會呼叫A的靜態建構函式,但是又因為strText屬於類A,而不是B,所以B得靜態建構函式不會執行,故輸出的均為AAA。
class Program
{
static void Main(string[] args)
{
B b = new B();
A a = new A();
Console.WriteLine(A.strText);
Console.WriteLine(B.strText);
Console.Read();
}
}
public class A
{
public static string strText;
public string Text;
static A()
{
strText = "AAA";
}
public A()
{
Text = "AAAAAAAAAAAAAAAAAAAAAAAAAA";
}
}
public class B : A
{
static B()
{
strText = "BBB";
}
public B()
{
Text = "BBBBBBBBBBBBBBBBB";
}
}
請注意我在開始部分對類進行了例項化,那麼此時的輸出結果就是均為BBB。
為什麼會有這樣的情況出現呢,其實還是要從靜態建構函式的呼叫時機入手。
首先我們例項化了B,此時會呼叫B的靜態建構函式,但是因為strText是A的靜態變數,所以首先會先呼叫A的靜態建構函式將strText賦值為AAA,此時又會呼叫B的靜態建構函式將strText賦值為BBB,所以此時strText的值應該為BBB,所以輸出均為BBB。
總結:靜態函式的呼叫時機,是在類被例項化或者靜態成員被呼叫的時候進行呼叫,並且是由.net框架來呼叫靜態建構函式來初始化靜態成員變數。
4.從建構函式中呼叫其他建構函式
class Car
{
private string description;
private uint nWheels;
public Car(string description,uint nWheels)
{
this.description = description;
this.nWheels = nWheels;
}
public Car(string description):this(description,4)
{
}
}
C#建構函式初始化器可以包含對同一個類的另一個建構函式的呼叫,也可以包含對直接基類的建構函式的呼叫(使用相同的語法,但應使用base關鍵字代替this)。初始化器中不能有多個呼叫。