一 创建对象时考虑实现比较器

假设有这样的场景,有一个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<T>接口的集合提供排序的功能。

改善C#程序的方法-3 比较器和LINQ排序的更多相关文章

  1. 改善C#程序的方法

    写在开头: http://www.cnblogs.com/luminji    157个建议_勘误表 一:属性 属性和方法一样.也可以是virtual和abstract. 条款2:运行时常量(read ...

  2. 改善C#程序的方法-1 操作字符串

    正确操作字符串 引言: 字符串是使用很频繁的一种数据类型. 如果使用不慎,则会为一次字符串操作所带来的额外性能开销而付出代价. 下面从这几个方面来探讨如何正确操作字符串: 1.确保尽量少的装箱,尽可能 ...

  3. 改善C#程序的方法-2 使用TryParse

    一 使用TryParse,而不是Parse 除string外的所有基元类型,都有两个将string类型转型为其本身类型的方法:Parse 和 TryParse. 以double类型为例,这两个方法最简 ...

  4. 编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器

    建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List< ...

  5. 编写高质量代码改善C#程序的157个建议——建议10: 创建对象时需要考虑是否实现比较器

    建议10: 创建对象时需要考虑是否实现比较器 有对象的地方就会存在比较,在.NET的世界中也一样.举个最简单的例子,在UI中,有一个10个人的Salary列表.根据排序的需要,列表要支持针对基本工资来 ...

  6. 改善C#程序,提高程序运行效率的50种方法

    改善C#程序,提高程序运行效率的50种方法   转自:http://blog.sina.com.cn/s/blog_6f7a7fb501017p8a.html 一.用属性代替可访问的字段 1..NET ...

  7. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  8. 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法

    建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...

  9. 编写高质量代码改善C#程序的157个建议——建议145:避免过长的方法和过长的类

    建议145:避免过长的方法和过长的类 如果违反“一个方法只做一件事”及类型的“单一职责原则”,往往会产生过长的方法和过长的类. 如果方法过长,意味着可以站在更高的层次上重构出若干更小的方法.以行数作为 ...

随机推荐

  1. SpringBoot集成文件 - 集成POI之Excel导入导出

    Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft Office格式档案读和写的功能.本文主要介绍通过Spr ...

  2. NOI / 2.5基本算法之搜索-6044:鸣人和佐助详解

    总时间限制: 1000ms 内存限制: 65536kB 题目 佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐助和鸣人的位置.地图上的每个位置都可以走到, ...

  3. DongDong认亲戚 来源:牛客网

    题目 链接:https://ac.nowcoder.com/acm/contest/28886/1021 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K, ...

  4. CS内网横向移动 模拟渗透实操 超详细

    @Webkio 前言: 最近在跟朋友搞一些项目玩,所以最近没怎么更新内容接下来我将在虚拟中模拟内网多层靶场,进行内网渗透实验,超详细,适合小白.本文仅供网安学习,不可利用于未授权渗透工作中,否则后果自 ...

  5. 技术分享 | 将GreatSQL添加到系统systemd服务

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1 ...

  6. CF859E 题解

    分析 我们不妨把这些座位看作是一张图中的节点,把每个人的诉求作为一条边(由[原座位]指向[想去的座位]) 比如,对于样例#1,我们就可以得到这样一张图: 显然,我们有可能会得到多个连通图(比如上面这张 ...

  7. 活动报名|对话贡献者:DolphinScheduler x Pulsar 在线 Meetup

    各位 DolphinScheduler 和 Pulsar 社区的小伙伴们,Apache DolphinScheduler x Pulsar 在线 Meetup 来啦! 导语 大数据任务调度.消息流的订 ...

  8. java-数组排序之冒泡排序(经典排序)

    public class BubbleSort { public static void main(String[] args) { /*冒泡排序不一定是用时最短的 * 1)声明整型数组arr,包含1 ...

  9. 监督学习集成模型——AdaBoost

    一.集成学习与Boosting 集成学习是指将多个弱学习器组合成一个强学习器,这个强学习器能取所有弱学习器之所长,达到相对的最佳性能的一种学习范式. 集成学习主要包括Boosting和Bagging两 ...

  10. flask 可插拔视图

    Flask 0.7 版本引入了可插拨视图.可插拨视图基于使用类来代替函数,其灵感来自于 Django 的通用视图.可插拨视图的主要用途是用可定制的.可插拨的视图来替代部分 实现.普通的函数视图 演示代 ...