C#例項構造器,型別構造器 -筆記
例項構造器: (引用型別)
例項構造器是一種特殊的方法,他們負責將型別(Class) 的例項初始化到一個良好的狀態.對於可驗證的程式碼,CLR要求每個類(引用型別)至少定義一個例項構造器。(可以是公開或私有)
在建立一個例項時系統將執行以下三個步驟:
1)首先為改例項分配記憶體;
2)然後初始化物件的附加成員(即方法表指標和一個SyncBlockIndex);
3)最後呼叫型別的構造器設定物件的初始狀態。在預設情況下,如果我們沒有顯式為其定義例項構造器,許多編譯器(包括C#)都會為我們定義一個共有的無參構造器。
//C# 編譯器會為我們自動的定義一個預設的公有無參構造器
class SomeType
{
}
//上面的型別定義等同於下面的型別定義
class SomeType
{
public SomeType()
{
}
}
一個型別可以定義多個例項構造器,每個構造器都必須有一個不同的簽名。
多個構造器可以有不同的訪問限制。
一個類的例項構造器在訪問其積累的繼承欄位之前,必須呼叫基類的例項構造器。
(許多編譯器,包括C#,都會自動產生對積累預設構造器(如果有的話)的呼叫程式碼,所以一般情況下,我們不用擔心這個問題。在少數情況下,型別例項的建立不需要呼叫例項構造器。例如:
1)呼叫Object的MemberwiseClone方法。
2)在反序列化一個物件時,通常也不會呼叫構造器。class SomeType
{
Int32 x=5;
String s="Hello";
Double d= 3.14;
Byte b;
//下面是一些構造器
public SomeType() {...}
public SomeType(Int32 x) {...}
public SomeType(String s(...,d=10;)
}當編譯器為以上三個構造器方法產生程式碼時的步驟:
1)每個方法的開始出都將包括 x, s, d 的初始化的程式碼。
2)在這些初始化程式碼之後,編譯器才會為各個構造器新增出現在其中的程式碼。
例如:對於接受String引數的那個構造器,編譯器產生的程式碼首先時初始化x,s,d, 然後才是將10賦值給d。* 如果我們有一些需要初始化的例項欄位,以及有許多過載的構造方法,我們應該考慮在定義欄位的時候避免同時對他們進行初始化,相反,我們應該將這些公共的初始化語句放在一個初始化構造器中。然後讓其他的構造器顯式呼叫這個初始化構造器,這將有效減少生成程式碼的尺寸。
以上程式碼可以改為
class SomeType
{
Int32 x;
String s;
Double d;
Byte b;
//下面是一些構造器
public SomeType()
{
x=5;
s="Hello";
d=3.14;
}
public SomeType(Int32 x) :this()
{ this.x=x; }
public SomeType(String s):this()
{
this.s=s;
d=10;
}
}
例項構造器:(值型別)
1)CLR沒有強制要求值型別中必須定義構造器方法。
2)CLR允許我們位置型別定義構造器。
(注意:但C#不允許我們為一個值型別定義無參構造器)-編譯器會丟擲出錯提示。3)一個值型別的例項構造器只有當被顯式呼叫時才會執行。(與引用型別的例項構造器不同)
struct SomeValType
{
Int32 x,y;
public SomeValType(Int32 x) {
this.x=this.y=x;
}
}
//正確的定義
class Ra {
public SomeValType val;
public Ra()
{
val= new SomeValType(1);
}
}
//必須顯式使用構造器。
//以下是錯誤內容
struct SomeValType
{
Int32 x=5;
}
//錯誤:因為C#不允許值型別有無參構造器,在編譯時會出錯:結構中不能有例項欄位初始值設定項
struct SomeValType
{
Int32 x,y;
public SomeValType(Int32 x) {
this.x=x;
}
}
//錯誤:y沒有被初始化,C#編譯器丟擲錯誤:。。。在控制離開構造器前,欄位SomeValType.y必須完全賦值。
型別構造器(又成為靜態構造器,類構造器)
1)預設情況下,一個型別中沒有定義型別構造器。
2)如果要定義型別構造器,也只能定義一個。
3)並且,型別構造器不能有任何引數
//當SomeType第一次被訪問是執行
class SomeType
{
static Int32 x;
static SomeType()
{
x=10;
}
}
struct SomeType
{
static Int32 x;
static SomeType()
{
x=10;
}
}
4)型別構造器必須是static,而且總是私有方式(預設只能由CLR完成,不能顯式指定)
5)型別構造器中的程式碼只能訪問型別的靜態欄位,並且通常他的目的就是初始化這些靜態欄位。
6)注意:型別構造器不應該呼叫其基型別的型別構造器。
不需要這樣作是因為基型別中的靜態欄位並沒有被派生型別所繼承(而只是編譯時靜態繫結)7)型別構造器的生成程式碼的順序與例項構造器中的處理方式完全相同
相關文章
- 構造器
- Java--構造器和構造方法Java構造方法
- java構造器Java
- this,構造器,static,final,單例模式單例模式
- 構造做題筆記筆記
- iOS提供指定構造器iOS
- Java構造器 小白版Java
- Effective Java - 構造器私有、列舉和單例Java單例
- 【lombok】@NoArgsConstructor/@RequirArgsConstructor/@AllArgsConstructor - 生成無參構造器,指定引數構造器或包含所有引數的構造器LombokStructUI
- 什麼是 Java 構造器?Java
- 物件導向和構造器物件
- C# List構造TreeViewC#View
- 構造器引用和直接用new建立物件區別物件
- java學習之深入構造器Java
- 理解 sole() 查詢構造器方法
- iOS 構造三級控制器iOS
- 直譯器構造文法簡述
- Day31--構造器詳解
- 3、用私有構造器或者列舉型別強化SIngleton屬性型別
- 【C++】構造資料型別--陣列C++資料型別陣列
- effective java 第2條:遇到多個構造器引數時要考慮用構造器Java
- 建議:用私有構造器或者列舉型別強化Singleton屬性。型別
- Effective Java - 靜態方法與構造器Java
- 621. 任務排程器 (構造)
- 構建一個 Javascript 多維陣列構造器JavaScript陣列
- 當未指定且存在多個構造器,例項化物件時Spring如何選擇?物件Spring
- 一文了解 Java 中的構造器Java
- 直譯器構造實現函式呼叫函式
- [Hibernate求助]如何構造自己的對映型別?型別
- PLSQL Language Referenc-PL/SQL集合和記錄-集合構造器SQL
- 遇到多個構造器引數時考慮使用構建器(Effective Java )Java
- C++ 建構函式實戰指南:預設構造、帶引數構造、複製構造與移動構造C++函式
- 構造方法構造方法
- C++物件模型之五 構造 析構 賦值筆記 (轉)C++物件模型賦值筆記
- 工作學習筆記(十二)java 無法將類 XX類中的構造器 X應用到給定型別筆記Java型別
- Java基礎03 構造器與方法過載Java
- 構造器中呼叫動態繫結的方法
- 使用 Laravel Eloquent 構造器讓模型更簡潔Laravel模型