频道栏目
读书频道 > 软件开发 > C# > 深入理解C#:第3版
1.2.1 按名称对产品进行排序
2014-03-21 16:09:48     我来说两句
收藏   我要投稿

本文所属图书 > 深入理解C#:第3版

本书是世界顶级技术专家十年磨一剑的经典之作,在C 和 NET领域享有盛誉。与其他泛泛介绍C 的书籍不同,本书深度探究C 的特性,并结合技术发展,引领读者深入C 的时空。作者从语言设计的动机出发,介绍支持这些特  立即去当当网订购

1.2 排序和过滤

本节不会改变Product类型,我们会使用示例的产品列表,并按名称排序,然后找出最贵的产品。每个任务都不难,但我们可以看到它到底能简化到什么程度。

1.2.1 按名称对产品进行排序

以特定顺序显示一个列表的最简单方式就是先将列表排好序,再遍历并显示其中的项。在.NET 1.1中,这要求使用ArrayList.Sort,而且在我们的例子中,要求提供一个IComparer实现。也可以让Product类型实现IComparable,但那就只能定义一种排序顺序。很容易就会想到,以后除了需要按名称排序,还可能需要按价格排序。

代码清单1-5实现了IComparer,然后对列表进行排序,并显示它。

代码清单1-5 使用IComparer对ArrayList进行排序(C# 1)
 

 

在代码清单1-5中,要注意的第一件事是,必须引入一个额外的类型来帮助排序。虽然这并不是一个大问题,但假如在一个地方只是想按名称进行排序,就会感觉编码工作过于繁重。其次,注意Compare方法中的强制类型转换。强制类型转换相当于告诉编译器:“嘿嘿,我知道的比你多一点点。”但是,这也意味着你可能是错误的。如果从GetSampleProducts返回的ArrayList包含一个字符串,那么代码会出错——因为在比较时试图将字符串强制转型为Product。

在给出排序列表的代码中也进行了强制类型转换。这个转换不如刚才的转换明显,因为是编译器自动进行的。foreach循环会隐式将列表中的每个元素转换为Product类型。同样,这种情况在执行时会失败,在C# 2中,“泛型”可以帮助我们解决这些问题。在代码清单1-6中,唯一的改变就是引入了泛型。

代码清单1-6 使用IComparer<Product>对List<Product>进行排序(C# 2)
 

 

在代码清单1-6中,对产品名进行比较的代码变得更简单,因为一开始提供的就是Product(而不可能是其他类型)。不需要进行强制类型转换。类似地,foreach循环中隐式的类型转换也被取消了。编译器仍然会考虑将序列中的源类型转换为变量的目标类型,但它知道这时两种类型均为Product,因此没必要产生任何用于转换的代码。

确实有了一定的改进。但是,我们希望能直接指定要进行的比较,就能开始对产品进行排序,而不需要实现一个接口来做这件事。代码清单1-7展示了具体如何做,它告诉Sort方法如何用一个委托来比较两个产品。

代码清单1-7 使用Comparison<Product>对List<Product>进行排序(C# 2)
 

 

注意,现在已经不再需要ProductNameComparer类型了。以粗体印刷的语句实际会创建一个委托实例。我们将这个委托提供给Sort方法来执行比较。第5章会更多地讲解这个特性(匿名方法)。

现在,我们已经修正了在C# 1的版本中不喜欢的所有东西。但是,这并不是说C# 3不能做得更好。首先,将匿名方法替换成一种更简洁的创建委托实例的方式,如代码清单1-8所示。

代码清单1-8 在Lambda表达式中使用Comparison<Product>进行排序(C# 3)
 

你又看到了一种奇怪的语法(一个Lambda表达式),它仍然会像代码清单1-7那样创建一个Comparison<Product>委托,只是代码量减少了。这里不必使用delegate关键字来引入委托,甚至不需要指定参数类型。

除此之外,使用C# 3还有其他好处。现在,可以轻松地按顺序打印名称,同时不必修改原始产品列表。代码清单1-9使用OrderBy方法对此进行了演示。

代码清单1-9 使用一个扩展方法对List<Product>进行排序(C# 3)
 


这里似乎调用了一个OrderBy方法,但查阅一下MSDN,就会发现这个方法在List <Product>中根本不存在。之所以能调用它,是由于存在一个扩展方法,第10章将讨论扩展方法的细节。这里实际不再是“原地”对列表进行排序,而只是按特定的顺序获取列表的内容。有时,你需要更改实际的列表;但有时,没有任何副作用的排序显得更“善解人意”。

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

本节又展示了一小部分C# 2和C# 3的强大功能,还有许多尚待解释的语法。但是,即使你还不理解这背后的细节,趋势也是相当明朗的:我们正在向更清晰、更简单的代码迈进!图1-2展示了这个演变过程。
 

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

到目前为止,我们只讲了排序[②]。现在来讨论一种不同的数据处理方式——查询。

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.1.4 C# 4中的命名实参
下一篇:1.2.2 查询集合
相关文章
图文推荐
排行
热门
最新书评
特别推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站