C#的自定義語法糖的使用詳解
語法糖(Syntactic sugar),也譯為糖衣語法,是由英國計算機科學家彼得·約翰·蘭達(Peter J. Landin)發(fā)明的一個術(shù)語,指計算機語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程序員使用。通常來說使用語法糖能夠增加程序的可讀性,從而減少程序代碼出錯的機會。
對If...Where的封裝——語法糖WhereIf(如果讀者已經(jīng)知曉,請自行跳過)
在做條件查詢的時候,我們可能經(jīng)常要寫這樣的代碼:
List<User> Query(User queryModel) { //定義一個演示數(shù)據(jù)集 List<User> userList = new List<User> { new User{ UserName = "燕雙鷹", Phone = "10369852103", Role = "正派" , Sex = true}, new User{ UserName = "沈七七", Phone = "14785203630", Role = "反派", Sex = true}, new User{ UserName = "步鷹", Phone = "14702021596", Role = "反派", Sex = true}, new User{ UserName = "小玲", Phone = "19469874106", Role = "正派", Sex = false}, new User{ UserName = "趙一平", Phone = "18502369740", Role = "反派", Sex = true} }; var data = userList.AsQueryable();//轉(zhuǎn)為IQueryable類型 //條件過濾 if (!string.IsNullOrEmpty(queryModel.UserName)) { data = data.Where(u => u.UserName == queryModel.UserName); } if (!string.IsNullOrEmpty(queryModel.Phone)) { data = data.Where(u => u.Phone == queryModel.Phone); } if (!string.IsNullOrEmpty(queryModel.Role)) { data = data.Where(u => u.Role == queryModel.Role); } if (queryModel.Sex != null) { data = data.Where(u => u.Sex == queryModel.Sex); } return data.ToList(); }
當傳入的參數(shù)不為空時,才執(zhí)行查詢。很明顯,這里大量的If-Where語句是極為簡單,且不斷重復出現(xiàn)的代碼(邏輯),可以進行封裝以簡化操作,以簡化代碼。
創(chuàng)建泛型擴展方法WhereIf,代碼如下:
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate) { return condition ? query.Where(predicate) : query; }
該方法實現(xiàn)了對If-Where的封裝,使用方法如下:
List<User> Query(User queryModel) { //定義一個演示數(shù)據(jù)集 List<User> userList = new List<User> { new User{ UserName = "燕雙鷹", Phone = "10369852103", Role = "正派" , Sex = true}, new User{ UserName = "沈七七", Phone = "14785203630", Role = "反派", Sex = true}, new User{ UserName = "步鷹", Phone = "14702021596", Role = "反派", Sex = true}, new User{ UserName = "小玲", Phone = "19469874106", Role = "正派", Sex = false}, new User{ UserName = "趙一平", Phone = "18502369740", Role = "反派", Sex = true} }; var data = userList.AsQueryable() .WhereIf(!string.IsNullOrEmpty(queryModel.UserName), u => u.UserName == queryModel.UserName) .WhereIf(!string.IsNullOrEmpty(queryModel.Phone), u => u.Phone == queryModel.Phone) .WhereIf(!string.IsNullOrEmpty(queryModel.Role), u => u.Role == queryModel.Role) .WhereIf(queryModel.Sex != null, u => u.Sex == queryModel.Sex); return data.ToList(); }
之前超過8行代碼的查詢代碼,被精簡到4行,代碼行數(shù)減少超過一半,可讀性大幅提高,由于只是簡單的封裝,運行效率幾乎不變。(減少大量代碼,提高可讀性,功能不變,效率不變,有優(yōu)無缺,因此強烈建議WhereIf來代替?zhèn)鹘y(tǒng)的If-Where操作。)
新的問題來了,If語句還存在一個條件不滿足的情況:else,WhereIf方法只封裝了IfWhere,卻沒有封裝If-Whrere-else-Where語句,如果遇到如下的查詢要求,要怎么做呢?
if (!string.IsNullOrEmpty(queryModel.UserName)) { data = data.Where(u => u.UserName == queryModel.UserName); } else { data = data.Where(u => u.UserName == "燕雙鷹");//如果查詢條件為空,就查詢燕雙鷹的姓名 }
有三個辦法可以解決這個問題:
第一個辦法,是修改WhereIf方法,增加else-Where的邏輯,使其支持If-Whrere-else-Where的邏輯:
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> truePredicate, Expression<Func<T, bool>> falsePredicate = null) => condition ? query.Where(truePredicate) : falsePredicate == null ? query : query.Where(falsePredicate);
這樣的做的缺點也是明顯的:在參數(shù)condition為false時,會進行第二次邏輯判斷,缺點是減低效率,優(yōu)點是代碼簡潔。(當然,多一個邏輯判斷也減低不了多少效率)
第二個方法,避免第二次邏輯判斷的方式是進行方法重載,也就是寫兩個WhereIf方法,在新增的這個WhereIf方法中,參數(shù)falsePredicate不再設置為可空參數(shù):
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> truePredicate, Expression<Func<T, bool>> falsePredicate) => condition ? query.Where(truePredicate) : query.Where(falsePredicate);
優(yōu)點是可以在不影響效率的情況下支持If-Whrere-else-Where邏輯,因為兩個WhereIf方法的邏輯是差不多的,缺點是又寫了簡單重復的代碼,不簡潔。(當然,僅僅是定義它的時候不簡潔,調(diào)用時候簡潔程度和方法一,是一樣的)
第三個方法,完全不修改WhereIf方法, 僅僅在調(diào)用的時候,通過對參數(shù)condition進行取反操作,來達到目的:
var data2 = data.WhereIf(!string.IsNullOrEmpty(queryModel.UserName), u => u.UserName == queryModel.UserName) .WhereIf(string.IsNullOrEmpty(queryModel.UserName), u => u.UserName == "燕雙鷹");
優(yōu)點:方法定義最簡單,缺點:在遇到If-Whrere-else-Where邏輯時,會增加代碼量。
具體選擇哪一種,請讀者自行斟酌,如果有更好的實現(xiàn)方法,就留言討論分享出來吧^_^
對for循環(huán)的封裝,語法糖For
實際開發(fā)中,很多時候?qū)or循環(huán)的使用,僅僅是將一個操作,循環(huán)指定的次數(shù),而且其中沒有break、continue這些提前終止循環(huán)的邏輯。這種簡單重復的邏輯可以進行提取封裝。
public static void For(int count, Action<int> action) { for (int i = 0; i < count; i++) { action.Invoke(i); } }
這里使用了C#的內(nèi)置泛型委托Action,發(fā)揮的作用就是將方法作為參數(shù)去傳遞。參數(shù)count表示循環(huán)總次數(shù),Action的參數(shù)int,表示正在進行的循環(huán)次數(shù),從0開始,讀者可以根據(jù)需要改成從1開始(這里從1開始好,還是從0開始好,待定)。
調(diào)用:
SyntacticSugar.For(1, p => { int a = p + 8; data2.Remove(data2[a]); });
如果認為這樣調(diào)用麻煩,可以在參數(shù)count前加this,使之變?yōu)閿U展方法,以簡化調(diào)用。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
c#異步操作async?await狀態(tài)機的總結(jié)(推薦)
這篇文章主要介紹了c#異步操作async?await狀態(tài)機的總結(jié),關于async和await每個人都有自己的理解,甚至關于異步和同步亦或者關于異步和多線程每個人也都有自己的理解,本文通過實例代碼詳細講解,需要的朋友可以參考下2023-02-02C#編程報錯System.InvalidOperationException問題及解決
這篇文章主要介紹了C#編程報錯System.InvalidOperationException問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-05-05C#利用ASP.NET?Core開發(fā)學生管理系統(tǒng)詳解
隨著技術(shù)的進步,跨平臺開發(fā)已經(jīng)成為了標配,在此大背景下,ASP.NET?Core也應運而生。本文主要利用ASP.NET?Core開發(fā)一個學生管理系統(tǒng),感興趣的可以學習一下2022-01-01C#將隱私信息(銀行賬戶,身份證號碼)中間部分特殊字符替換成*
大家在銀行交易某些業(yè)務時,都可以看到無論是身份證、銀行賬號中間部分都是用*號替換的,下面這篇文章主要介紹C#將隱私信息(銀行賬戶,身份證號碼)中間部分特殊字符替換成*的相關資料,需要的朋友可以參考下2015-08-08