最近看到一個使用Lambda + LINQ不好的例子,舉例:
資訊公司員工辛苦上市,尾牙特別獎賞員工
- 每人最起碼發放10000獎金
- 假如入職滿一年獎金 +20000,滿兩年獎金 +40000
- 因為資訊部門KPI特別好,增加額外獎金 +30000
以下是模擬
他的寫法,可以看到缺點
重複呼叫方法
GetYearDif難以維護
void Main()
{
//測試資料,實際上資料在Excel
var datas = new List<Employee>(){
new Employee{Name="小明",Department=Dep.資訊部,EntryDate=DateTime.Parse("2015/01/01")},
new Employee{Name="小華",Department=Dep.資訊部,EntryDate=DateTime.Parse("2017/01/01")},
new Employee{Name="小新",Department=Dep.業務部,EntryDate=DateTime.Parse("2014/01/01")}
};
NewYearBonusService.Excute(datas);
}
abstract class NewYearBonusService
{
private const decimal DefaultBonus = 10000;
public static void Excute(IEnumerable<Employee> datas)
{
datas.Select(s => new {Employee = s,bonus=
s.Department == Dep.資訊部 && GetYearDif(DateTime.Now, s.EntryDate) >= 2 ? DefaultBonus + 30000 + 40000 :
s.Department == Dep.資訊部 && GetYearDif(DateTime.Now, s.EntryDate) >= 1 ? DefaultBonus + 30000 + 20000:
s.Department == Dep.資訊部 ? DefaultBonus + 30000:
DefaultBonus
}).Dump();
}
private static int GetYearDif(DateTime d1, DateTime d2)
{
var dif = (int)((d2 - d1).TotalDays / 365);
if (dif < 0) dif *= -1;
return dif;
}
}
enum Dep{ 資訊部,業務部 }
class Employee{
public string Name { get; set; }
public Dep Department { get; set; }
public DateTime EntryDate { get; set; }
}
詢問對方才發現他以為只能使用expression body,不知道可以使用statement body
,在這個例子其實可以改成語句塊
作法,如以下範例:
1.可以加上if判斷
2.宣告變數重複利用
3.甚至可以做簡單防呆
abstract class NewYearBonusService
{
private const decimal DefaultBonus = 10000;
public static void Excute(IEnumerable<Employee> datas)
{
datas.Select(s =>
{
var bonus = DefaultBonus;
var yearDif = GetYearDif(DateTime.Now,s.EntryDate);
if (s == null) throw new Exception("資料為空,請檢查資料");
if (s.Department == Dep.資訊部 ) bonus+=30000;
if (yearDif>=2) bonus+=40000; else if (yearDif>=1) bonus+= 20000;
return new { Employee=s ,bonus};
}
).Dump();
}
}
為什麼可以這麼方便?可以藉由反編譯程式碼看到底層還是委託(delegate)
,只是系統幫我們生成而已。