一 创建对象时考虑实现比较器
假设有这样的场景,有一个40个人的学生列表,业务中需针对学生的成绩来进行排序。
可以考虑用IComparable接口和ICompare接口实现:- class Program
- {
- static void Main(string[] args)
- {
- var stus = new List<Student>();
- stus.Add(new Student() { Name = "zhangsan", EnglishGrades = 80.5, MathGrades = 90 });
- stus.Add(new Student() { Name = "lisi", EnglishGrades = 74, MathGrades = 91 });
- stus.Add(new Student() { Name = "wangwu", EnglishGrades = 94, MathGrades = 85.5 });
- stus.Add(new Student() { Name = "zhaoliu", EnglishGrades = 88.5, MathGrades = 86 });
-
- stus.Sort();
- Console.WriteLine("使用默认比较器排序:");
- foreach (var stu in stus)
- {
- Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
- }
-
- stus.Sort(new MathComparer());
- Console.WriteLine("使用自定义比较器排序:");
- foreach (var stu in stus)
- {
- Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
- }
- Console.ReadLine();
- }
- }
- //Student通过IComparable接口,实现默认比较器
- class Student : IComparable<Student>
- {
- public string Name { get; set; }
- public double EnglishGrades { get; set; }
- public double MathGrades { get; set; }
- public int CompareTo(Student stu)
- {
- if (EnglishGrades > stu.EnglishGrades)
- {
- return 1;
- }
- else if (EnglishGrades == stu.EnglishGrades)
- {
- return 0;
- }
- else
- {
- return -1;
- }
- //return EnglishGrades.CompareTo(stu.EnglishGrades); double类型的默认比较方法
- }
- }
- //通过IComparer接口实现自定义的比较器
- class MathComparer : IComparer<Student>
- {
- public int Compare(Student x, Student y)
- {
- return x.MathGrades.CompareTo(y.MathGrades);
- }
- }
复制代码 输出:- 使用默认比较器排序:
- Name:lisi, English:74, Math:91
- Name:zhangsan, English:80.5, Math:90
- Name:zhaoliu, English:88.5, Math:86
- Name:wangwu, English:94, Math:85.5
- 使用自定义比较器排序:
- Name:wangwu, English:94, Math:85.5
- Name:zhaoliu, English:88.5, Math:86
- Name:zhangsan, English:80.5, Math:90
- Name:lisi, English:74, Math:91
复制代码 二 使用LINQ取代集合中的比较器
上述的方法实现的排序存在2个问题:
- 可扩展性太低,如果存在新的排序要求,就必须实现新的比较器;
- 对代码的侵入性太高,为类型继承了接口,新增了方法。
LINQ提供了类似于SQL的语法来实现遍历、筛选和投影集合的强大功能,可以实现上述的排序要求。- static void Main(string[] args)
- {
- var stus = new List<Student>();
- stus.Add(new Student() { Name = "zhangsan", EnglishGrades = 80.5, MathGrades = 90 });
- stus.Add(new Student() { Name = "lisi", EnglishGrades = 74, MathGrades = 91 });
- stus.Add(new Student() { Name = "wangwu", EnglishGrades = 94, MathGrades = 85.5 });
- stus.Add(new Student() { Name = "zhaoliu", EnglishGrades = 88.5, MathGrades = 86 });
- var orderByStus = from s in stus orderby s.EnglishGrades select s;
- //orderByStus = stus.OrderBy(s => s.EnglishGrades);
- foreach (var stu in orderByStus)
- {
- Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
- }
- Console.WriteLine();
-
- orderByStus = from s in stus orderby s.MathGrades select s;
- //orderByStus = stus.OrderBy(s => s.MathGrades);
- foreach (var stu in orderByStus)
- {
- Console.WriteLine($"Name:{stu.Name},\tEnglish:{stu.EnglishGrades},\tMath:{stu.MathGrades}");
- }
- Console.ReadLine();
- }
复制代码 LINQ此功能的实现本身是借助于FCL泛型集合的比较器、迭代器和索引器。LINQ封装了这些功能,让我们使用更加方便。
在命名空间System.Linq下的Enumerable方法中为泛型集合提供了很多扩展方法。
如排序中使用到的OrderBy方法:- public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector);
复制代码 它为继承了IEnumerable接口的集合提供排序的功能。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |