C#开发的进化史(排序和过滤)

    本次不会改变product类型,会使用产品列表,并按名称排序,而后找出最贵的产品spa

1、按名称对产品进行排序.net

    以特定顺序显示一个列表的最简单方式就是先将列表排好序,在遍历显示其中的项。blog

 (一) 在.net1.1中,这要求使用ArrayList.Sort,要求提供一个IComparer实现。也可让product类型实现IComparable,但那就只能定义一种排序顺序。很容易就会想到,之后除了须要按名称排序,还可能须要按价格排序排序

                          使用IComparer对ArrayList进行排序接口

 class productNameComparer : IComparer
    {
        public int Compare(object x, object y)
        {
            Product first = (Product)x;
            Product second = (Product)y;
            return first.Name.CompareTo(second.Name);
        }

    }

......
         ArrayList products = Product.GetSanpleProducts();
            products.Sort(new productNameComparer());
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }
            Console.ReadKey();        

  要注意的第一件事是:必须引入一个的类型来帮助排序。虽然这并非一个很大的问题,但假如在一个地方只是项按名称进行排序,就会感受编译工做过于繁重。其次,注意Comparer方法中强制类型转换。强制类型转换至关于告诉编译器:“我知道发比你多一点点,”可是,也就意味着多是错误的。若是GetSanpleProducts返回的是ArrayList包含一个字符串,那么代码会出错——由于在比较时试图将字符串强制转型为product。开发

  (二)在给出排序列表的代码中也进行了强制类型转换。这个转换不如刚才的转换显示,由于是编译器自动进行的。foreach循环会隐式将列表中的每一个元素转换为product类型。这样的状况在执行时会失败,在C#2“泛型”能够帮助解决这些问题字符串

                                              使用Icomparer对List<product>进行排序编译器

  class productNameComparer : IComparer<Product>     {
        public int Compare(Product x, Product y)
        {
            return x.Name.CompareTo(y.Name);
        }
    }
......
 List<Product> products = Product.GetSanpleProducts();
            products.Sort(new productNameComparer());
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  对产品进行比较的代码变得更简单,由于一开始提供的就是product。不须要进行强制类型转换。相似地,foreach循环中隐式的类型转换也被取消了。编译器仍然会考虑将序列中的源类型转换为变量的目标类型,但它知道这时两种类型均为product,所以不必产生任何用于转换的代码。产品

  但愿能直接指定要进行的比较,就能开始对产品进行排序,而不须要实现一个接口来作这件事。it

                                              使用Comparison对List<product>进行排序

List<Product> products = Product.GetSanpleProducts();
            products.Sort(delegate (Product x, Product y)
            {
                return x.Name.CompareTo(y.Name);
            });

            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }
            Console.ReadKey();

  如今已经不在须要productNameComparer类型了。以粗体印刷的语句实际会建立一个委托实例,将这个委托实例提供给Sort方法来执行比较

(三)已经修正了在C#1的版本中不喜欢的全部东西。可是,这并非说C#3不能作到更好。首先,将匿名方法替换成一种更简洁的建立委托实例的方式

                                              lambda表达式中使用Comparison排序

 List<Product> products = Product.GetSanpleProducts();
            products.Sort((x, y) => x.Name.CompareTo(y.Name));
            foreach (Product product in products)
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  看到了一种奇怪的语法(一个lambda表达式),它仍然建立了一个Comparison<product>委托,只是代码量减小。这里没必要使用delegate关键字来引入委托,甚至不须要指定参数类型

  除此以外,使用C#3还有其余好处,如今,能够轻松的按顺序打印名称,同时没必要修改原始产品列表。

                                              使用扩展方法对List<product>进行排序

 List<Product> products = Product.GetSanpleProducts();
            foreach (Product product in products.OrderBy(p=>p.Name))
            {
                Console.WriteLine(product);
            }

            Console.ReadKey();

  这里彷佛调用一个OrderBy方法,但查阅一下MSDN,就会发现这个方法在LIst<product>中根本不存在。之因此能调用它,是因为存在一个扩展方法。这里实际不在是“原地”对列表进行排序,而只是按特定的顺序获取列表的内容。有时,须要更改实际的列表;但有时,没有任何反作用的排序显得更“善解人意”。

(四)总结

  重点在于,如今的写法更简洁,可读性更好。想法是“列表按名称排序”,如今的代码正是这样作的。并非“列表经过将产品的名称与另外一个产品的名称进行比较来排序”,就像C#2代码所作的那样。也不是使用知道如何将一个产品与另外一个产品进行比较的另外一个类型的实例来排序。这种简化的表达方式是C#3的核心有事之一。既然单独的数据查询和操做是如此简单,那么在执行更大规模的数据处理时,仍然能够保存代码的简洁性和可读性,这进而鼓励开发者以一种“以数据为中心”的方式来观察世界。

                                在C#2和C#3中用于简化排序的特性

  1.C#1:弱类型的比较功能不支持委托排序

  2.C#2强类型的比较更能,委托比较,匿名方法

  3.C#3:表达式,扩展方法,容许列表保持为排序状态

相关文章
相关标签/搜索