C#中的ThenBy是如何实现的
2013-12-27 00:10
190 查看
C#中的ThenBy是如何实现的
C#中给继承自IEnumerable的对象(最熟知的就是List了)提供了很丰富的扩展方法,涉及列表操作的方方面面。而扩展方法ThenBy就是很有意思的一个,它的实现也很巧妙。如果有这样的一个Team类,里面有三个属性。
Team.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public class Team { public Team (string name, int timeCost, int score) { this.Name = name; this.TimeCost = timeCost; this.Score = score; } public string Name { get; private set; } public int TimeCost { get; private set; } public int Score { get; private set; } } |
1 2 3 4 5 | List<Team> teams = new List<Team> (); teams.Add (new Team ("teamA", 10, 22)); teams.Add (new Team ("teamB", 12, 20)); teams.Add (new Team ("teamC", 8, 18)); |
1 2 | var result = teams.OrderByDescending (team => team.Score).First (); Console.WriteLine (result.Name); // teamA |
如果我的List变成这个样子。
1 23 | List<Team> teams = new List<Team> (); teams.Add (new Team ("teamA", 10, 18)); teams.Add (new Team ("teamB", 12, 16)); teams.Add (new Team ("teamC", 8, 18)); |
1 | var result = teams.OrderByDescending (team => team.Score).OrderBy(team => team.TimeCost).First (); |
那么应该如何实现那?C#给我们提供了一个叫做ThenBy的方法,可以满足我们的要求。
1 23 | var result = teams.OrderByDescending (team => team.Score).ThenBy(team => team.TimeCost).First (); Console.WriteLine (result.Name); // teamC |
这就先要看OrderByDescending方法是如何实现了的。查看源码发现OrderByDescending有两个重载,实现如下。
1 2 3 4 56 | public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { return source.OrderByDescending (keySelector, null); } public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey> (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { Check.SourceAndKeySelector (source, keySelector); return new OrderedSequence<TSource, TKey> (source, keySelector, comparer, SortDirection.Descending); } |
而我们再查看下ThenBy方法的定义。
1 2 3 4 56 | public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer) { Check.SourceAndKeySelector (source, keySelector); return source.CreateOrderedEnumerable<TKey> (keySelector, comparer, false); } public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey> (this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector) { return source.ThenBy (keySelector, null); } |
1 2 3 4 56 | using System; using System.Collections; using System.Collections.Generic; namespace System.Linq { public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable { // // Methods // IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey> (Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending); } } |
所以玄机在OrderedSequence这个类上。实现了IEnumerable接口对象调用OrderBy后会返回OrderedSequence这个对象。而该对象记录了当前排序的规则,其实现了IOrderedEnumerable接口。而ThenBy扩展方法被加到了IOrderedEnumerable接口对象上,其返回值也是一个具有IOrderedEnumerable接口的对象。
照这么说,调用了一次OrderBy后,然后调用多次ThenBy也是可以工作的。我也从官方MSDN中找到了答案:
ThenBy and ThenByDescending are defined to extend the type IOrderedEnumerable, which is also the return type of these methods. This design enables you to specify multiple sort criteria by applying any number of ThenBy or ThenByDescending methods.
翻译为: ThenBy及ThenByDescending是IOrderedEnumerable类型的扩展方法。ThenBy和ThenByDescending方法的返回值也是IOrderedEnumerable类型。这样设计是为了能够调用任意数量的ThenBy和ThenByDescending方法实现多重排序。
至此,ThenBy的神秘面纱就解开了,但是我不知道如何查看OrderedSequence类的源码,如果能看到这个类的源码就太完美了。知道的同学请告知方法。
注: 上述类的源码来自于Mono的实现。
相关文章推荐
- C#中的ThenBy是如何实现的
- C#:ListView控件如何实现点击列表头进行排序
- 在C#中如何实现Form与Form之间的通信
- C#&nbsp;如何让多行TextBox实现换行
- 如何使用C#实现QQ号码的申请
- C#如何实现单例启动和关闭全部窗体
- C# 使用多线程如何传递两个以上参数的实现方法(附示例) 推荐
- C#中如何实现AVI视频的播放并且需要在播放视频的同时在视频上进行一些简单线条的绘制?
- C#浮动的窗口如何实现
- [转]如何在C#用WM_COPYDATA消息来实现两个进程之间传递数据
- 看看C# Hook 如何实现
- 如何用c#实现仿QQ会员右下角提示框
- 在java中如何实现C#语法里的按引用传递参数
- 在C#中主线程和子线程如何实现互相传递数据
- 如何实现C#与matlab交互
- C# 如何实现带消息数的App图标
- WinFrom+C# 如何实现发布并自动升级
- C#如何实现Object与byte[]的互相转换
- 在C#中如何实现List的比较
- [ASP.NET教程] C#中如何实现数据拖动?(拖动图片,到TextBox,并显示)