Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得
利用迭代搭配委派輸入參數,可同時得到原始集合封裝性與自定義執行方法的彈性。接下來要來談一個實務上會遇到的問題;若是在迭代的過程中,執行的委派方法拋出了例外,且方法包含了修改集合元素狀態的邏輯,該如何回復前一個正常的狀態呢?以下用一個範例演示。
範例情境:
var allEmployees = FindAllEmployees( );
allEmployees.ForEach( e => e.MonthlySalary *= 1.05M );
若是在某一個元素執行委派方法時拋出了例外,系統無從得知該如何回覆先前狀態。
要解決這個問題,可以從兩個地方下手;一個是利用提前檢查元素狀態,若不符合前置條件則不執行(而非執行後拋出例外)。另一個是利用集合副本的方式,分配另一塊記憶體執行委派方法,若期間沒拋出例外則將原始物件指向新的副本。
做法一,利用前置條件檢查。
allEmployees.FindAll(
e => e.Classification == EmployeeType.Active ).
ForEach( e => e.MonthlySalary *= 1.05M );
做法二,利用集合副本重新指派新的物件。
var updates = ( from e in allEmployees
select new Employee
{
EmployeeID = e.EmployeeID,
Classification = e.Classification,
YearOfService = e.YearOfService,
MonthlySalary = e.MonthlySalary * 1.05M
} ).ToList( );
allEmployees = updates;
兩種做法都有其適用情境,第一種做法需確保例外拋出不會發生在 e.MonthlySalary *= 1.05M,但不需額外記憶體空間;而第二種做法包含了所有可能的例外狀況,但需額外分配記憶體。
Note:若委派方法不包含改變集合元素狀態,則不需考慮其是否可回復先前狀態。
例如:
var total = allEmployees.Aggregate( 0M,
( sum, emp ) => sum + emp.MonthlySalary );
結論:
1. 避免在迭代中,拋出輸入委派方法的例外。
2. 若無可避免有機會拋出例外,可利用前置條件檢查或是集合副本的方式實作。
1. 避免在迭代中,拋出輸入委派方法的例外。
2. 若無可避免有機會拋出例外,可利用前置條件檢查或是集合副本的方式實作。