C#的自定義語法糖的使用詳解
語法糖(Syntactic sugar),也譯為糖衣語法,是由英國計(jì)算機(jī)科學(xué)家彼得·約翰·蘭達(dá)(Peter J. Landin)發(fā)明的一個(gè)術(shù)語,指計(jì)算機(jī)語言中添加的某種語法,這種語法對(duì)語言的功能并沒有影響,但是更方便程序員使用。通常來說使用語法糖能夠增加程序的可讀性,從而減少程序代碼出錯(cuò)的機(jī)會(huì)。
對(duì)If...Where的封裝——語法糖WhereIf(如果讀者已經(jīng)知曉,請(qǐng)自行跳過)
在做條件查詢的時(shí)候,我們可能經(jīng)常要寫這樣的代碼:
List<User> Query(User queryModel)
{
//定義一個(gè)演示數(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();
}
當(dāng)傳入的參數(shù)不為空時(shí),才執(zhí)行查詢。很明顯,這里大量的If-Where語句是極為簡單,且不斷重復(fù)出現(xiàn)的代碼(邏輯),可以進(jìn)行封裝以簡化操作,以簡化代碼。
創(chuàng)建泛型擴(kuò)展方法WhereIf,代碼如下:
public static IQueryable<T> WhereIf<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> predicate)
{
return condition
? query.Where(predicate)
: query;
}
該方法實(shí)現(xiàn)了對(duì)If-Where的封裝,使用方法如下:
List<User> Query(User queryModel)
{
//定義一個(gè)演示數(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ùn)行效率幾乎不變。(減少大量代碼,提高可讀性,功能不變,效率不變,有優(yōu)無缺,因此強(qiáng)烈建議WhereIf來代替?zhèn)鹘y(tǒng)的If-Where操作。)
新的問題來了,If語句還存在一個(gè)條件不滿足的情況: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 == "燕雙鷹");//如果查詢條件為空,就查詢燕雙鷹的姓名
}
有三個(gè)辦法可以解決這個(gè)問題:
第一個(gè)辦法,是修改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);
這樣的做的缺點(diǎn)也是明顯的:在參數(shù)condition為false時(shí),會(huì)進(jìn)行第二次邏輯判斷,缺點(diǎn)是減低效率,優(yōu)點(diǎn)是代碼簡潔。(當(dāng)然,多一個(gè)邏輯判斷也減低不了多少效率)
第二個(gè)方法,避免第二次邏輯判斷的方式是進(jìn)行方法重載,也就是寫兩個(gè)WhereIf方法,在新增的這個(gè)WhereIf方法中,參數(shù)falsePredicate不再設(shè)置為可空參數(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)點(diǎn)是可以在不影響效率的情況下支持If-Whrere-else-Where邏輯,因?yàn)閮蓚€(gè)WhereIf方法的邏輯是差不多的,缺點(diǎn)是又寫了簡單重復(fù)的代碼,不簡潔。(當(dāng)然,僅僅是定義它的時(shí)候不簡潔,調(diào)用時(shí)候簡潔程度和方法一,是一樣的)
第三個(gè)方法,完全不修改WhereIf方法, 僅僅在調(diào)用的時(shí)候,通過對(duì)參數(shù)condition進(jìn)行取反操作,來達(dá)到目的:
var data2 = data.WhereIf(!string.IsNullOrEmpty(queryModel.UserName), u => u.UserName == queryModel.UserName)
.WhereIf(string.IsNullOrEmpty(queryModel.UserName), u => u.UserName == "燕雙鷹");
優(yōu)點(diǎn):方法定義最簡單,缺點(diǎn):在遇到If-Whrere-else-Where邏輯時(shí),會(huì)增加代碼量。
具體選擇哪一種,請(qǐng)讀者自行斟酌,如果有更好的實(shí)現(xiàn)方法,就留言討論分享出來吧^_^
對(duì)for循環(huán)的封裝,語法糖For
實(shí)際開發(fā)中,很多時(shí)候?qū)or循環(huán)的使用,僅僅是將一個(gè)操作,循環(huán)指定的次數(shù),而且其中沒有break、continue這些提前終止循環(huán)的邏輯。這種簡單重復(fù)的邏輯可以進(jì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,表示正在進(jìn)行的循環(huán)次數(shù),從0開始,讀者可以根據(jù)需要改成從1開始(這里從1開始好,還是從0開始好,待定)。
調(diào)用:
SyntacticSugar.For(1, p => { int a = p + 8; data2.Remove(data2[a]); });
如果認(rèn)為這樣調(diào)用麻煩,可以在參數(shù)count前加this,使之變?yōu)閿U(kuò)展方法,以簡化調(diào)用。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。
上一篇:C#SuperSocket的搭建并配置啟動(dòng)總結(jié)
欄 目:C#教程
本文標(biāo)題:C#的自定義語法糖的使用詳解
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/4761.html
您可能感興趣的文章
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并打開的方法
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#停止線程的方法
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新聞效果的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已安裝軟件變化的方法
- 01-10C#實(shí)現(xiàn)多線程下載文件的方法


閱讀排行
本欄相關(guān)
- 01-10C#通過反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)


