使用C# Linq的確給我們帶來(lái)了很多的方便,但是如果不合理使用,會(huì)造成一些隱藏的bug,而且很難被發(fā)現(xiàn)。
今天我就分享一個(gè)工作中遇到的問(wèn)題。
需求:對(duì)list進(jìn)行遍歷,把滿足某一條件的item Remove掉。
List<ClassA> list = new List<ClassA>(); for (int i = 0; i < 1000; i++) { list.Add(new ClassA()); }
il.ForEach(x => il.Remove(x));
?
為了簡(jiǎn)化代碼,在此不加條件語(yǔ)句。
以上代碼貌似是把list中所有的item都Remove掉,但其實(shí)不然。
可以看到在執(zhí)行完ForEach之后list中還有500項(xiàng)。
想必高手們應(yīng)該之后了吧?在對(duì)list進(jìn)行刪除的時(shí)候,list整個(gè)集合的index已經(jīng)發(fā)生了變化。
Remove一次,原來(lái)集合的index就會(huì)整體向前移動(dòng)一個(gè)。
?
原index:
3,4,5,6
Remove()后
index:
2,3,4,5
?
其實(shí)以上代碼等價(jià)于:
List<IA> list = new List<IA>(); for (int i = 0; i < 1000; i++) { list.Add(new ClassA()); } for (int i = 0; i < 500; i++) { list.Remove(list[i]); }
所以應(yīng)對(duì)以上bug,并且使用簡(jiǎn)介的Linq,正確的辦法是:
for (int i = 0; i <list.Count; i++) { ??? if (list[i].a==0) ??? { ??????? list.RemoveAt(i); ??????? i--; ??? } }
?
list.ToList().ForEach(x => { if (x.a==0) { list.Remove(x); } });
ToList()會(huì)new 一個(gè)list,然后對(duì)新的list進(jìn)行遍歷,刪除舊list中與之對(duì)應(yīng)index的值,至少這樣的寫(xiě)法是對(duì)的。但是最優(yōu)的辦法是使用List<T>中的RemoveAll(Predicate<T> match)方法,該方法還會(huì)return 被刪除的items的個(gè)數(shù)。
list.RemoveAll(x => x.a == 0);
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
