iT邦幫忙

5

【C#】小知識 #6 : Lambda + LINQ 使用statement body(語句塊)不使用expression情況

c#

最近看到一個使用Lambda + LINQ不好的例子,舉例:

資訊公司員工辛苦上市,尾牙特別獎賞員工

  • 每人最起碼發放10000獎金
  • 假如入職滿一年獎金 +20000,滿兩年獎金 +40000
  • 因為資訊部門KPI特別好,增加額外獎金 +30000

以下是模擬他的寫法,可以看到缺點

  1. 重複呼叫方法 GetYearDif
  2. 每個條件寫一個三元運算式,條件變多會難以維護
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();
	}
}

2018-12-26.21.22.23-image.png

為什麼可以這麼方便?可以藉由反編譯程式碼看到底層還是委託(delegate),只是系統幫我們生成而已。
2018-12-26.11.25.19-image.png

補充

  1. 這是LINQ + Lambda才能使用的方法,單純LINQ是不能簡單套用
    2018-12-26.11.37.20-image.png
  2. 使用編輯器是LINQPAD,Dump()是裡面的擴充方法,可以用Console.WriteLine取代

尚未有邦友留言

立即登入留言