Item1:Always Use Properties Instead of Accessible Data Members
屬性是C#語言中一個很重要的特性,我們可以使用屬性對成員進行封裝。
從編譯器的角度來看,屬性就是針對成員變數兩個方法:get_xxx和set_xxx,這一點和Java是很像的,當我們在Java中定義個成員變數,然後通過重構產生相應的屬性時,對應的方法名就是get_xxx和set_xxx。
為什麼要使用屬性來代替成員變數呢?我認為從類的職責劃分的角度進行理解會更好一些,當一個類向外公開一個訪問入口時,這個入口可以是公開的方法、屬性或者成員變數,那麼從封裝變化的觀點來看,類本身應該對自身變數的異常進行處理,而不是由調用方進行處理。因此,如果是堅持使用公開的成員變數,那麼對變數的異常處理,只能由調用方來進行處理,這樣做是不合理的。一方面,同樣的異常處理在多個調用方進行,會出現大量的重複代碼,另一方面,當業務發生變化,成員變數的邏輯有改變時,需要修改每個調用該變數的地方,這將會是一件令人非常抓狂的事情。
使用屬性代替成員變數,有以下好處:
- 可以在set或者get中對異常情況進行統一處理,或者可以在set和get中對多線程進行統一處理。
- 可以通過設定set和get的方式將屬性置為可讀寫的,也可以通過只設定get不設定set的方式,將屬性置為唯讀,這樣可以避免調用方對屬性的值進行錯誤的賦值。
- 由於set和get可以看做是方法的形式,那麼它們就可以使用方法的訪問限制符,例如可以將set設定為private,將get設定為public,這樣,對於屬性來說,它的調用方還是不能為其賦值,從另外的角度實現了唯讀屬性。當然還可以使用其他限制符,例如protected、internal等。
- 可以在介面中聲明屬性,也可以在抽象類別中聲明抽象屬性。這樣在進行架構設計時,可以為具體業務留出足夠的空間。
- 我們可以對屬性的外延進行擴充,進而討論索引器,索引器的形式:this[int i]{set;get},索引器也包括set和get,同時"[]"中可以是數字,也可以是其他字串。當我們通過索引器進行資料繫結時,要求"[]"中必須是數字。
使用屬性會降低程式的效能嗎?
一般來說,是不會的,首先,.NET程式運行時,是採用JIT的方式進行的,如果會影響效能,那麼只能是在第一次啟動並執行時候;其次,編譯器在對屬性進行編譯時間,會採用內嵌函式的方式,對set和get進行處理,這樣的結果,和直接存取資料成員差別很小,基本可以忽略不計。
注意:當我們將類中公開的成員變數重構為屬性後,需要重新編譯所有使用到這個屬性的類,因為這個重構的操作破壞了二進位的相容性。