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

假设有这样的场景,有一个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. DDS信号发生器加强版(双通道,发送波形的频率可控,相位可控,种类可控)

    目的:设计一个DDS,可以输出两个波形,输出的波形的周期可以修改,相位可以修改,种类也可以修改 输入:clk,reset,一个控制T的按键,一个控制相位的按键,一个控制波形种类的按键. 思路:双通道- ...

  2. kubernetes 静态存储与动态存储

    静态存储   Kubernetes 同样将操作系统和 Docker 的 Volume 概念延续了下来,并且对其进一步细化.Kubernetes 将 Volume 分为持久化的 PersistentVo ...

  3. SpringWeb 拦截器

    前言 spring拦截器能帮我们实现验证是否登陆.验签校验请求是否合法.预先设置数据等功能,那么该如何设置拦截器以及它的原理如何呢,下面将进行简单的介绍 1.设置 HandlerInterceptor ...

  4. Axure RP 8 实现 圆角文本框 圆角带筛选的下拉列表框 可自动显示滚动条

    刚开始用Axure 会发现 Axure 元件库并不是很齐全,很多元件需要自己想办法解决 或者去网上去找.其实个人建议网上有现成的元件可以就下载就不必花时间去折腾.除非你也想练练手,原型这种东西除非高保 ...

  5. 珠联壁合地设天造|M1 Mac os(Apple Silicon)基于vscode(arm64)配置搭建Java开发环境(集成web框架Springboot)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_194 也许有人从未听说过Python,但是不会有人没听说过Java,它作为一个拥有悠久历史的老牌编程语言,常年雄踞TIOBE编程语 ...

  6. Blazor和Vue对比学习(进阶2.2.3):状态管理之状态共享,Blazor的依赖注入和第三方库Fluxor

    Blazor没有提供状态共享的方案,虽然依赖注入可以实现一个全局对象,这个对象可以拥有状态.计算属性.方法等特征,但并不具备响应式.比如,组件A和组件B,都注入了这个全局对象,并引用了全局对象上的数据 ...

  7. WorkflowAsCode 来了,Apache DolphinScheduler 2.0.2 惊喜发布

    文章目录 前言 01 新功能 1 WorkflowAsCode 2 企业微信告警方式支持群聊消息推送 02 优化 1 简化元数据初始化流程 2 删除补数日期中的"+1"(天) 03 ...

  8. LuoguP1858 多人背包(DP)

    第\(K\)优解这类问题可在\(DP\)过程中通过添维解决.归并出当前前\(K\)大的解. #include <iostream> #include <cstdio> #inc ...

  9. 一文了解.Net的CLR、GC内存管理

    一文了解.Net的CLR.GC内存管理 微软官方文档对内存管理和CLR的概述 什么是托管代码? 托管代码就是执行过程交由运行时管理的代码. 在这种情况下,相关的运行时称为公共语言运行时 (CLR),不 ...

  10. Think PHP 完整的带富文本格式以及图片上传,并且在页面上分页展示

    Think php6.0官网网址:序言 · ThinkPHP6.0完全开发手册 · 看云 (kancloud.cn) 下面是基础配置 第一步:创建TP框架,命名为tp composer create- ...