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

假设有这样的场景,有一个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. 透过Redis源码探究Hash表的实现

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/667 本文使用的Redis 5.0源码 概述 我们在学习 Redis ...

  2. 在 Windows msys2 下编译 scryer-prolog

    by chesium 2022/7/24 深夜 参考:https://github.com/mthom/scryer-prolog/blob/master/README.md 采用 msys2 环境编 ...

  3. Netty-ProtobufVarint32

    效果 ProtobufVarint32LengthFieldPrepender编码器用于在数据最前面添加Varint32,表示数据长度 ProtobufVarint32FrameDecoder是相对应 ...

  4. 第十六天python3 文件IO(二)

    BytesIO操作 io模块中的类 from io import BytesIO 内存中,开辟的一个二进制模式的buffer,可以像文件对象一样操作它: 当close方法被调用的时候,这个buffer ...

  5. 从零开始搭建Vue2.0项目(一)之快速开始

    从零开始搭建Vue2.0项目(一)之项目快速开始 前言 该样板适用于大型,严肃的项目,并假定您对Webpack和有所了解vue-loader.确保还阅读vue-loader的文档,了解常见的工作流程配 ...

  6. python操作ini文件

    简介 ini文件作为常见的配置文件,因此需要对ini文件做处理,此处使用configparser模块,本文介绍以下ini文件常用的处理方式. 需要读取的ini文件 如下文件,[ ]包含的称为secti ...

  7. Vue 路由的简单使用(命名路由、query路由传参、params路由传参)

    1 # Vue 路由 2 # 1.理解:一个路由(toute)就是一组映射关系(key-value),多个路由需要路由器(router)进行管理 3 # 2.前端路由:key是路径,value是组件 ...

  8. PureRandom采样类定义和测试

    此是随机采样算法,效果感觉一般般. 类声明: #pragma once #ifndef __PURERANDOM_HEADER__ #define __PURERANDOM_HEADER__ #inc ...

  9. Jenkins使用pipeline部署服务到远程服务器

    写这篇文章是对之前搭建Jenkins做的修改和完善,让jenkins更好的为我们服务 Docker搭建Jenkins服务 使用过程中遇到的问题: 为方便部署,打算将jenkins用到的jdk11.ma ...

  10. BZOJ3894/LuoguP4313 文理分科 (最小割)

    #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> ...