2013-02-27
8.1 例項構造器和類(引用型別)
8.2 例項構造器和結構(值型別)
8.3 型別構造器
8.6 擴充套件方法返回
建立引用型別的例項的過程:
(1) 為例項的資料字段分配記憶體(例項字段包括本身及其基類的例項字段)
(2) 然後初始化物件的附加字段(型別物件指標和同步塊索引)
(3) 呼叫型別的例項構造器來設定物件的初始狀態。
基類的構造器總是在類的例項構造器之前呼叫,這是為了使**「可驗證」(當類的例項構造器訪問從基類繼承來的字段)。因此,不要再構造器中呼叫虛方法(比如這個虛方法要在子類中重寫,可是重寫方法所用欄位還沒初始化)。
c#提供簡單語法,允許在構造引用型別例項時,對型別中定義的字段進行「內聯」初始化:
1class
sometype
2
我們通過sometype構造器的il**發現,字段初始化的**會在幕後移入到構造器中,構造器il**的執行順序為:字段初始化=》基類構造器=》構造器本身的**,因此,盡量把初始化任務放在構造器中。
和其他方法不同,例項構造器永遠不能被繼承。
c#編譯器將定義乙個預設(無參)構造器,下表顯示類修飾符與預設構造器的關係。
表1類修飾符與預設構造器的關係
類的修飾符
預設構造器
無abstract
預設構造器可訪問性為public
有abstract
預設構造器可訪問性為protected
static(靜態類在元資料中是抽象密封類)
編譯器根本不會在類中定義生成乙個預設構造器返回
值型別(struct)構造器的工作方式與引用型別(class)的構造器截然不同。c#編譯器根本不會為值型別生成無參構造器。即使為值型別提供了無參構造器,許多編譯器也永遠不會生成**呼叫它。c#編譯器乾脆不允許值型別定義無參構造器,也不允許值型別中內聯方式初始化例項字段。
注意:嚴格的說,只有當值型別的字段巢狀到引用型別中時,才保證會被初始化為0或null。但是,基於棧的值型別欄位不保證為0或null。
為了**的「可驗證性」(verifiablity),任何基於棧型別的子型別都必須在讀取前寫入(賦值)。如果允許**先讀再寫,就會造成安全漏洞,所以c#和其他生成「可驗證」**的編譯器可以保證對它們進行「置零」。返回
型別預設沒有定義型別構造器,如果定義,也只能定義乙個。此外,型別構造器永遠沒有引數。
型別構造器必須標記為static,而且,總是私有的,c#會自動把它們標記為private。
型別構造器不應呼叫其基型別的型別構造器。這種呼叫沒有必要,因為型別並沒有從其基型別繼承靜態字段。返回
對無法修改的類擴充其方法,要小心使用。
《CLR via C 》讀書筆記 之 引數
2013 02 27 預設情況下,clr假定所有方法引數都是傳值的。當傳遞引用型別的物件時,也預設是傳值的,只不過這個值是引用 指標 本身。clr允許以傳引用的方式傳遞引數。在c 中,用關鍵字out或ref來告訴編譯器。編譯器將傳遞引數的位址,而不是傳遞引數本身。從clr角度看,out和ref完全一...
CLR via C 讀書筆記1 9
與非託管 的互操作 clr 提供3種與非託管 的互動方案 託管 通過使用 p invoke 機制 來呼叫dll檔案中的非託管函式 許多 fcl 中定義的型別內部都有呼叫到 kernel32.dll,user32.dll 等等檔案中的函式。同時許多程式語言會提供託管 呼叫非託管 的簡便途徑,比如 c ...
CLR via C 讀書筆記2 2
把型別編譯成乙個模組 先假設有這麼乙個簡單的程式 public sealed class program 該程式定義乙個名為 program 的型別,它擁有乙個公有靜態 public,static 方法 main,該方法參照 system.console。把源 存為 program.cs 執行以下命...