VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • 改善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>接口的集合提供排序的功能。


出处:https://www.cnblogs.com/wwwen/p/16524999.html


相关教程