改善C#程序的方法-3 比较器和LINQ排序
一 创建对象时考虑实现比较器
假设有这样的场景,有一个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排序的更多相关文章
- 改善C#程序的方法
写在开头: http://www.cnblogs.com/luminji 157个建议_勘误表 一:属性 属性和方法一样.也可以是virtual和abstract. 条款2:运行时常量(read ...
- 改善C#程序的方法-1 操作字符串
正确操作字符串 引言: 字符串是使用很频繁的一种数据类型. 如果使用不慎,则会为一次字符串操作所带来的额外性能开销而付出代价. 下面从这几个方面来探讨如何正确操作字符串: 1.确保尽量少的装箱,尽可能 ...
- 改善C#程序的方法-2 使用TryParse
一 使用TryParse,而不是Parse 除string外的所有基元类型,都有两个将string类型转型为其本身类型的方法:Parse 和 TryParse. 以double类型为例,这两个方法最简 ...
- 编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器
建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List< ...
- 编写高质量代码改善C#程序的157个建议——建议10: 创建对象时需要考虑是否实现比较器
建议10: 创建对象时需要考虑是否实现比较器 有对象的地方就会存在比较,在.NET的世界中也一样.举个最简单的例子,在UI中,有一个10个人的Salary列表.根据排序的需要,列表要支持针对基本工资来 ...
- 改善C#程序,提高程序运行效率的50种方法
改善C#程序,提高程序运行效率的50种方法 转自:http://blog.sina.com.cn/s/blog_6f7a7fb501017p8a.html 一.用属性代替可访问的字段 1..NET ...
- 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)
编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...
- 编写高质量代码改善C#程序的157个建议——建议150:使用匿名方法、Lambda表达式代替方法
建议150:使用匿名方法.Lambda表达式代替方法 方法体如果过小(如小于3行),专门为此定义一个方法就会显得过于繁琐.比如: static void SampeMethod() { List< ...
- 编写高质量代码改善C#程序的157个建议——建议145:避免过长的方法和过长的类
建议145:避免过长的方法和过长的类 如果违反“一个方法只做一件事”及类型的“单一职责原则”,往往会产生过长的方法和过长的类. 如果方法过长,意味着可以站在更高的层次上重构出若干更小的方法.以行数作为 ...
随机推荐
- while练习题_1到100之间的偶数和
依然是while循环四步骤 初始化变量 条件判断 条件执行体 最后就是输出答案就可以了 点击查看笔者代码 a = 1 sum = 0 while a <= 100: if (a+1)%2:#if ...
- 5.1 从C到C++
在前4章中介绍了C语言的主要内容,已经足以应付许多算法竞赛的题目了,然而能写不代表好写,有些虽然能够用C语言实现,但是使用C++写起来往往会更快,并且不容易出错 从c到c++ C语言是一门很有用的语言 ...
- SQL语言的总结
SQL语言分类:1.数据查询语言(DQL:Data Query Language),也称为"数据检索语句",用以从表中查询获得数据,常用关键字SELECT (一般常用的语句是:SE ...
- html的基础01
1.什么是网页 2.常用的浏览器有哪些 3.web标准是什么 1.什么是网页 2.常用的浏览器 360.百度那些都是国产浏览器,内核一样,以上六个都是国际浏览器,不同厂商生产(但IE和Edge都是 ...
- YII学习总结3(session)
session操作 <?php namespace app\controllers; use yii\web\Controller; class HelloController extends ...
- 无意苦争春,一任群芳妒!M1 Mac book(Apple Silicon)能否支撑全栈工程师的日常?(Python3/虚拟机/Docker/Redis)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_187 就像大航海时代里突然诞生的航空母舰一样,苹果把玩着手心里远超时代的M1芯片,微笑着对Intel说:"不好意思,虽然 ...
- 当我们谈论算法我们在谈论什么:由疫情核酸检测想到的分治算法(Divide-and-Conquer)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_159 北京的疫情一波未平一波又起,由此看来,战"疫"将是一场旷日持久的战争,绝不能掉以轻心.轻易言胜.病毒随时 ...
- 【沥血整理】灰度(二值)图像重构算法及其应用(morphological reconstruction)。
不记得是怎么接触并最终研究这个课题的了,认识我的人都知道我是没有固定的研究对象的,一切看运气和当时的兴趣.本来研究完了就放在那里了,一直比较懒的去做总结,但是想一想似乎在网络上就没有看到关于这个方面的 ...
- mybatis 09: 动态sql --- part1
作用 可以定义代码片段 可以进行逻辑判断 可以进行循环处理(批量处理),使条件判断更为简单 使用方式 通过mybatis中与动态sql有关的标签来实现 < sql >标签 + < i ...
- DS队列----银行单队列多窗口模拟
题目描述 假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙.当有窗口空闲时,下一位顾客即去该窗口处理事务.当有多个窗口可选择时,假设顾客总是选择编号最小的窗口. 本 ...