大家应该都知道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();
01-12 04:28