大家應該都知道Int32.Parse()是不安全,但有時可能會有僥幸心理,而我正是在這樣的心理驅使下,這么干了。相關場景簡化處理后的代碼,如下。
List<BookInfo> bookLst = new List<BookInfo>();
for (var i = 0; i < 100000000; i++)
{
bookLst.Add(new BookInfo() {
Num = i.ToString()
});
}
//原有寫法
var finalBookLst1= bookLst.Where(p => Int32.Parse(p.Num) > 10).ToList();
public class BookInfo
{
public string Num { get; set; }
}
很顯然,在linq的where條件之中,直接進行類型轉換是不安全的,基於此我們需要對這段代碼進行優化。
既然是對集合進行操作,那么我們可以使用for循環,來替代原有的where條件,因此便有了下面一段代碼。
var finalBookLst2= new List<BookInfo>();
for (var j = 0; j < bookLst.Count; j++)
{
int num1;
Int32.TryParse(bookLst[j].Num,out num1);
if (num1 > 10)
finalBookLst2.Add(bookLst[j]);
}
在上述代碼中,我們直接遍歷集合中的每一個對象,對其進行業務判斷后,將滿足條件的對象加入到預期結果的集合之中,最后我們便得到了最終的結果。
用for循環寫完之后,我的第一想法就是這多low呀,性能得多差呀。於是乎經過了一番百度,我們的第二個方案便產生了。
ConcurrentBag<BookInfo> finalBookLst3 = new ConcurrentBag<BookInfo>();
Parallel.For(0,bookLst.Count,(num)=> {
int num2;
Int32.TryParse(bookLst[num].Num,out num2);
if (num2 > 10)
finalBookLst3.Add(bookLst[num]);
});
Parallel主要用於任務的並行執行,在上面的示例中,我們將我們業務判斷通過Parallel並行執行,希望能夠優化響應時間。但是,悲催的是,使用Parallel的方案更加耗時。
從以上示例可以看出,並行執行並不一定比串行執行效率高,因為並行執行是有額外開銷。同時需要支出的是,List是線程不安全的,因此我們使用ConcurrentBag<T>來保存處理結果。
而對於bookLst的訪問,由於不存在資源競爭,所以是安全。
木得辦法,由於Parallel性能太差,我們是要舍棄這種方案的,想要替代for循環還得另尋它法,最后便有了如下代碼的產生,這也是我們最終選擇的方案。
private static bool CheckNum(BookInfo bookInfo)
{
int num;
Int32.TryParse(bookInfo.Num, out num);
if (num > 10)
return true;
else
return false;
}
var finalBookLst4 = bookLst.Where(new Func<BookInfo,bool>(CheckNum)).ToList();
