本文章對書中 50 個做法進行總整理,以及對每個做法做出簡短總結,方便日後查看。
Chapter 1. Working with Data Types
- 01.Use Properties Instead of Accessible Data Members :
保存資料只使用
private field
搭配public properties
與protected properties
對外開放存取,永遠不要使用public field
。 - 02.Prefer Implicit Properties for Mutable Data :
當資料是可變類型時建議直接使用
Auto-implemented properties
。 - 03.Prefer Immutability for Value Types :
準備使用
Value Types
時最好讓它具備Immutable
特性。 - 04.Distinguish Between Value Types and Reference Types :
區分
Value Types
與Reference Types
的分別,如果不確定在設計中使用Value Types
對應用程式是否有幫助那最好不要使用。 - 05.Ensure That 0 Is a Valid State for Value Types :
使用
Enum
時一定要確保0
具備有效的狀態。 - 06.Ensure That Properties Behave Like Data : 要讓屬性存取保持輕量,不要讓它在背後做出大家意料之外的事情。
- 07.Limit Type Scope by Using Anonymous Types :
說明
Anonymous Types
與Tuple Types
並不會消耗這麼多資源,如果使用Tuple Types
則資料會具備Mutable
特性 - 08.Define Local Functions on Anonymous Types : 透過建立高階函式可以將匿名函式與 lambda 當成引數來傳遞。
- 09.Understand the Relationships Among the Many Different Concepts of Equality :
在覆寫相等性檢查方法時不要去覆寫
static bool ReferenceEquals()
與static bool Equals
,另外當型別為Value Types
則需要覆寫Equals()
方法與==
運算子並同時實做IEquatable<T>
介面。 - 10.Understand the Pitfalls of GetHashCode() :
說明設計
GetHashCode()
方法的最佳實踐以及覆寫Equals()
方法的時候同時要覆寫GetHashCode()
方法。
Chapter 2. API Design
- 11.Avoid Conversion Operators in Your APIs :
最好不要使用
implicit
與explicit
操作子處理轉型工作。 - 12.Use Optional Parameters to Minimize Method Overloads :
使用
Optional Parameters
可以讓減少方法多載的版本數量並增加可讀性。 - 13.Limit Visibility of Your Types :
建議最好只保留程式可運作的最低可見性,而不是一昧的只使用
public
。 - 14.Prefer Defining and Implementing Interfaces to Inheritance :
說明
Interfaces
比起Abstract Class
使用上彈性來的大的多。 - 15.Understand How Interface Methods Differ from Virtual Methods :
說明
Interfaces
設計彈性比較高並且能在內部使用abstract
與virtual
修飾方法。 - 16.Implement the Event Pattern for Notifications :
講解
EventHandler
背後運作的機制以及可以用來解除發佈者跟訂閱者之間的耦合。 - 17.Avoid Returning References to Internal Class Objects : 說明資料封裝的重要性,要避免私有資料的參考傳出物件外。
- 18.Prefer Overrides to Event Handlers :
說明在處理
WinForm
專案的事件時應該優先使用覆寫,其他複雜的場合再考慮 Attach 到既有事件 - 19.Avoid Overloading Methods Defined in Base Classes : 解釋不要在衍生類別多載基底類別存在的方法,並說明編譯器解析正確方法的順序。
- 20.Understand How Events Increase Runtime Coupling Among Objects : 說明事件是怎麼導致釋放流程推遲執行的。
- 21.Declare Only Nonvirtual Events :
宣告
virtual event
會造成理解上的誤會導致誤用最好不要這樣使用。 - 22.Create Method Groups That Are Clear, Minimal, and Complete : 提供幾條建議讓我們在處理 API 多載時能夠更加實用。
- 23.Give Partial Classes Partial Methods for Constructors, Mutators, and Event Handlers :
使用
Partial Classes
與Partial Methods
能夠把邏輯分散到多個檔案中,也可以讓一般工程師與程式碼產生器不會互相干擾。 - 24.Avoid ICloneable because it limits your design choices :
建議不要實做
ICloneable
因為會影響繼承關係,並且沒有辦法清楚得知實做的內容是Deep Copy
還是Shallow Copy
。 - 25.Limit Array Parameters to Params Arrays :
使用
Params Array
帶來的方便性與好處。 - 26.Enable Immediate Error Reporting in Iterators and Async Methods using Local Functions :
使用
Local Functions
能夠將某段私有邏輯封裝在某個方法內部,避免被其他人使用。
Chapter 3. Task based Asynchronous Programming
- 27:Use Async methods for async work :
建議現在開發非同步程式優先使用
async
和await
。 - 28:Never Write Async void Methods :
不要使用
async void
因為它並不會帶來任何好處還必須搭配補助程式碼才能順利運行。 - 29:Avoid Composing Synchronous and Asynchronous Methods : 不要在非同步方法裡面混用同步邏輯,因為可能會導致死鎖。
- 30:Use async Methods to Avoid Thread Allocations and Context Switches : 不要產生無意義的 Context Switches,因為它會影響程式性能
- 31:Avoid Marshalling Context Unnecessarily :
說明 Context 對於執行緒的意義以及建議非同步方法都加上
ConfigureAwait(false)
。 - 32:Compose Asynchronous Work Using Task Objects : 介紹 Task 常用的幾個 API。
- 33:Consider Implementing the Task Cancellation Protocol : 介紹 Task 的取消與回報功能。
- 34:Cache Generalized Async Return types :
說明大量建立 Task 會影響程式的性能,可以使用緩存或
ValueTask
來改善。
Chapter 4. Parallel Processing
- 35:Learn How PLINQ Implements Parallel Algorithms : 講解 PLINQ 背後運作的機制以及常用的擴充方法
- 36:Construct Parallel Algorithms with Exceptions in Mind : 建立平行運算方法時需要額外小心例外處理,因為它的運作邏輯與一般方法不同。
- 37:Use the Thread Pool Instead of Creating Threads : 說明 Thread Pool 能夠自動管理執行緒,在大量建立執行緒的場合會對性能有大大的改善。
- 38:Use BackgroundWorker for Cross-Thread Communication :
介紹
BackgroundWorker
以及常用的進度回報、任務取消、異常處理等功能。 - 39:Understand Cross-Thread Calls in XAML environments : 說明和處理 WinForm 與 WPF 在非同步的環境下更新 UI 的問題。
- 40:Use lock() as Your First Choice for Synchronization :
介紹
Monitor
、lock
、Interlocked
,應該首先考慮使用Interlocked
類別,如果不符合需求在使用lock
。 - 41:Use the Smallest Possible Scope for Lock Handles : 說明鎖定有公開性的物件會導致的問題,建議在類別產生私有的鎖物件。
- 42:Avoid Calling Unknown Code in Locked Sections : 建議要縮小 lock 的鎖定範圍,如果將大量不相干的程式碼加到範圍內會增加死鎖風險。
Chapter 5. Dynamic Programming
- 43:Understand the Pros and Cons of Dynamic : 說明靜態型別與動態型別的好處與壞處。
- 44:Use Dynamic to Leverage the Runtime Type of Generic Type Parameters :
說明
Cast<T>
方法的缺陷並且說明如何用dynamic
把轉型缺失的資訊補上。 - 45:Use DynamicObject or IDynamicMetaObjectProvider for Data Driven Dynamic Types :
介紹
DynamicObject
與IDynamicMetaObjectProvider
如何在執行時期建立出一個新的型別。 - 46:Understand How to Make Use of the Expression API :
介紹
Expression API
以及Expression Trees
的相關概念 - 47:Minimize Dynamic Objects in Public APIs :
說明使用
dynamic
的物件時首先要避免過度蔓延,並且要利用額外的設計來限制dynamic
的影響範圍
Chapter 6. Participate in the global C# Community
- 48:Seek the best answer, not the most popular answer : 建議不要只看最熱門的答案,應該要嘗試尋找更完美的解決方案並且分享出去。
- 49:Participate in Specs and Code : 建議多參與開源的專案同時能夠貢獻程式碼又能提升自己的能力。
- 50:Consider automating practices with Analyzers : 可以在專案安裝分析器這樣能夠加快審查的過程並減輕維護的工作量。