Effective C 原則14 使用建構函式鏈

2021-04-27 16:44:36 字數 2743 閱讀 2877

effective c# 原則14:使用建構函式鏈

item 14: utilize constructor chaining

寫建構函式是乙個反覆的工作。很多開發人員都是先寫乙個建構函式,然後複製貼上到其它的建構函式裡,以此來滿足類的一些過載介面。希望你不是這樣做的,如果是的,就此停止吧。有經驗的c++程式可能會用乙個輔助的私有方法,把常用的演算法放在裡面來構造物件。也請停止吧。當你發現多重建構函式包含相同的邏輯時,取而代之的是把這些邏輯放在乙個常用的建構函式裡。你可以得避免**的重複的好處,並且建構函式初始化比物件的其它**執行起來更高效。c#編譯器把建構函式的初始化識別為特殊的語法,並且移除預置方法中重複的變數和重複的基類建構函式。結果就是這樣的,你的物件最終執行最少的**來合理的初始化物件。你同樣可以寫最少的**來把負責委託給乙個常用的建構函式。建構函式的預置方法充許乙個構造函式呼叫另乙個建構函式。這是乙個簡單的例子:

public class myclass

public myclass( int initialcount ) :

this( initialcount, "" )

public myclass( int initialcount, string name )

}c#不支援帶預設值的引數,c++是很好的解決這個問題的(譯註:c++可以讓引數有預設的值,從而有效的減少函式的過載)。你必須重寫每乙個特殊的建構函式。對於這樣的建構函式,就意味著大量的**重複工作。可以使用建構函式鏈來取代常規的方法。下面就是一些常規的低效率的建構函式邏輯:

public class myclass

public myclass( int initialcount )

public myclass( int initialcount, string name )

private void commonconstructor( int count,

string name )

}這個版本看上去是一樣的,但生成的效率遠不及物件的其它**。為了你的利益,編譯器為建構函式新增了一些**。新增了一些**來初始化所有的變數(參見原則12)。它還呼叫了基類的建構函式。當你自己寫一些有效的函式時,編譯器就不會新增這些重複的**了。第二個版本的il**和下面寫的是一樣的:

// not legal, illustrates il generated:

public myclass()

public myclass (int initialcount)

public myclass( int initialcount, string name )

private void commonconstructor( int count,

string name )

}如果你用第乙個版本寫建構函式,在編譯看來,你是這樣寫的:

// not legal, illustrates il generated:

public myclass()

public myclass (int initialcount)

public myclass( int initialcount, string name )

}不同之處就是編譯器沒有生成對基類的多重呼叫,也沒有複製例項變數到每乙個建構函式內。實際上基類的建構函式只是在最後乙個建構函式裡被呼叫了,這同樣很重要:你不能包含更多的建構函式預置方法。在這個類裡,你可以用this()把它委託給另乙個方法,或者你可以用base()呼叫基類的構造。但你不能同時呼叫兩個。

還不清楚建構函式預置方法嗎?那麼考慮一下唯讀的常量,在這個例子裡,物件的名字在整個生命期內都不應該改變。這就是說,你應該把它設定為唯讀的。如果使用輔助函式來構造物件就會得到乙個編譯錯誤:

public class myclass

public myclass( int initialcount )

public myclass( int initialcount, string name )

private void commonconstructor( int count,

string name )

}c++程式會把這個_name留在每乙個建構函式裡,或者通常是在輔助函式裡把它丟掉。c#的建構函式預置方法提供了乙個好的選擇,幾乎所有的瑣碎的類都包含不只乙個建構函式,它們的工作就是初始化物件的所有成員變數 。這是很常見的,這些函式在理想情況下有相似的共享邏輯結構。使用c#構造預置方法來生成這些常規的演算法,這樣就只用寫一次也只執行一次。

這是c#裡的最後乙個關於物件構造的原則,是時候複習一下,乙個型別在構造時的整個事件順序了。你須要同時明白乙個物件的操作順序和預設的預置方法的順序。你構造過程中,你應該努力使所有的成員變數只精確的初始化一次。最好的完成這個目標的方法就是盡快的完成變數的初始化。這是某個型別第一次構造乙個例項時的順序:

1、靜態變數儲存位置0。

2、靜態變數預置方法執行。

3、基類的靜態建構函式執行。

4、靜態建構函式執行。

5、例項變數儲存位置0。

6、例項變數預置方法執行。

7、恰當的基類例項建構函式執行。

8、例項建構函式執行。

後續的同樣型別的例項從第5步開始,因為類的預置方法只執行一次。同樣,第6和第7步是優化了的,它可以讓編譯器在建構函式預置方法上移除重複的指令。

c#的編譯器保證所有的事物在初始化使用同樣的方法來生成。至少,你應該保證在你的型別建立時,物件占用的所有記憶體是已經置0的。對靜態成員和例項成員都是一樣的。你的目標就是確保你希望執行的初始化**只執行一次。使用預置方法來初始化簡單的資源,使用建構函式來初始化一些具有複雜邏輯結構的成員。同樣,為了減少重複盡可能的組織呼叫其它的建構函式。

《Effective C艹》讀書筆記(14)

條款21 當必須返回物件時,別妄想返回其reference 並不是在任何情況下都可以通過傳引用的方式返回值。看下面這段 const rational operator const rational r1,const rational r2 事實上,任何對這個函式返回值的讀寫操作都將返回錯誤,因為返回...

Effective C 學習筆記 第一彈 1 4

條款1 盡量以const和inline取代 define 1 當這麼做時 define pi 3.1415 pi 在編譯之前會被預處理器移走,而並沒有進去符號表,當除錯時,你能看到3.1415,但是找不到pi。2 常量指標 如 const int p int a 1 int b 2 p a p 3 ...

敏捷外包的14條原則

敏捷外包的14條原則 文 vikas hazrati 譯 金欣亮 雖然軟體專案的外包趨勢已經是乙個不爭的事實,但是還是有很多專案由於錯誤的外包而失敗了。拋開諸多優勢不談,軟體外包確實帶來了額外的複雜性 風險以及消耗。本文將基於實際專案經驗以及豐田公司的製造過程,討論如何把外包變成一種成功的模式,我們...