C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现)

摘要:
IComparable和IComparer IComparable<=;的通用实现;集合;}#regionIComparableMemberspublicintCompareTo(objectobj){Studentstudent=objasStudent;}elseif(Age==student.Age){return0;

C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现)

本文摘要:

1:比较和排序的概念;

2:IComparable和IComparer;

3:IComparable和IComparer的泛型实现IComparable<T>和IComparer<T>;

1:比较和排序的概念

    比较:两个实体类之间按>,=,<进行比较。

    排序:在集合类中,对集合类中的实体进行排序。排序基于的算法基于实体类提供的比较函数。

    基本型别都提供了默认的比较算法,如string提供了按字母进行比较,int提供了按整数大小进行比较。

2:IComparable和IComparer

    当我们创建了自己的实体类,如Student,默认想要对其按照年龄进行排序,则需要为实体类实现IComparable接口。

    
    class Student:IComparable
    {
        public string Name { get; set; }
        public int Age { get; set; }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            Student student = obj as Student;
            if (Age > student.Age)
            {
                return 1;
            }
            else if (Age == student.Age)
            {
                return 0;
            }
            else
            {
                return -1;
            }
            //return Age.CompareTo(student.Age);
        }
        #endregion
    }

    PS:注意上面代码中CompareTo方法有一条注释的代码,其实本函数完全可以使用该注释代码代替,因为利用了整形的默认比较方法。此处未使用本注释代码,是为了更好的说明比较器的工作原理。
    接下来写一个测试用例:
        public Form1()
        {
            InitializeComponent();
            studentList = new ArrayList();
            studentList.Add(new Student() { Age = 1, Name = "a1" });
            studentList.Add(new Student() { Age = 5, Name = "g1" });
            studentList.Add(new Student() { Age = 4, Name = "b1" });
            studentList.Add(new Student() { Age = 2, Name = "f1" });
        }
        ArrayList studentList;
        private void button1_Click(object sender, EventArgs e)
        {
            studentList.Sort();
            foreach (Student item in studentList)
            {                
                this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n"  ;
            }
        }

      运行结果:

a1----1
f1----2
b1----4
g1----5

      OK,疑问来了。如果不想使用年龄作为比较器了,那怎么办。这个时候IComparer的作用就来了,可使用IComparer来实现一个自定义的比较器。如下:

    class SortName: IComparer
    {
        #region IComparer Members

        public int Compare(object x, object y)
        {
            Student s1 = x as Student;
            Student s2 = y as Student;
            return s1.Name.CompareTo(s2.Name);
        }

        #endregion
    }

      这个时候,我们在排序的使用为Sort方法提供此比较器:

      studentList.Sort(new SortName());

      运行的结果是:

a1----1
b1----4
f1----2
g1----5

            

3:IComparable和IComparer的泛型实现IComparable<T>和IComparer<T>

      如果我们稍有经验,我们就会发现上面的代码我们使用了一个已经不建议使用的集合类ArrayList。当泛型出来后,所有非泛型集合类已经建议不尽量使用了。至于原因,从上面的代码中我们也可以看出一点端倪。

      注意查看这个Compare函数,如:

        public int Compare(object x, object y)
        {
            Student s1 = x as Student;
            Student s2 = y as Student;
            return s1.Name.CompareTo(s2.Name);
        }

      我们发现这个函数进行了装箱和拆箱。而这是会影响性能的。如果我们的集合中有成千上万个复杂的实体对象,则在排序的时候所耗费掉的性能就是客观的。而泛型的出现,就可以避免掉拆箱和装箱。

      故上文代码中的ArrayList,应该换成List<T>,对应的,我们就该实现IComparable<T>和IComparer<T>。最终的代码应该像:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            studentList = new List<Student>();
            studentList.Add(new Student() { Age = 1, Name = "a1" });
            studentList.Add(new Student() { Age = 5, Name = "g1" });
            studentList.Add(new Student() { Age = 4, Name = "b1" });
            studentList.Add(new Student() { Age = 2, Name = "f1" });
        }
        List<Student> studentList;
        private void button1_Click(object sender, EventArgs e)
        {
            studentList.Sort(new SortName());

            foreach (Student item in studentList)
            {
                
                this.textBox1.Text += item.Name + "----" +item.Age.ToString() + "\r\n"  ;
            }
        }
    }

    class Student:IComparable<Student>
    {
        public string Name { get; set; }
        public int Age { get; set; }

        #region IComparable<Student> Members

        public int CompareTo(Student other)
        {
            return Age.CompareTo(other.Age);
        }

        #endregion
    }

    class SortName: IComparer<Student>
    {
        #region IComparer<Student> Members

        public int Compare(Student x, Student y)
        {
            return x.Name.CompareTo(y.Name);
        }

        #endregion
    }
 C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现)第1张微信扫一扫,关注最课程(www.zuikc.com),获取更多我的文章,获取软件开发每日一练
练习:
1.You are creating a class named Age.  You need to ensure that the Age class is written such that collections of
Age objects can be sorted. Which code segment should you use? 
A. public class Age    {       public int Value;        
public object CompareTo(object obj)   
{       if (obj is Age) 
{          Age _age = (Age) obj;                  
return Value.CompareTo(obj);         }      
throw new ArgumentException("object not an Age");          }    }
B. public class Age {       
public int Value;        
public object CompareTo(int iValue) {           
try {            
return Value.CompareTo(iValue);       }  
catch {            
throw new ArgumentException ("object not an Age");                 }     }  }
C. public class Age : IComparable {       
public int Value;        
public int CompareTo(object obj)   
{         if (obj is Age) {                  
Age _age = (Age) obj;           
return Value.CompareTo(_age.Value);       }       
throw new ArgumentException("object not an Age");          }    }
D. public class Age : IComparable {       
public int Value;        
public int CompareTo(object obj) {        
try {            
return Value.CompareTo(((Age) obj).Value);       } 
catch {            
return -1;         }     }   } 
Answer: C
2.You are creating a class to compare a specially-formatted string. The default collation comparisons do not apply.     
You need to implement the IComparable<string> interface.   Which code segment should you use? 
A. public class Person : IComparable<string>{       public int CompareTo(string other){          ...   }}
B. public class Person : IComparable<string>{       public int CompareTo(object other){        ...   }}
C. public class Person : IComparable<string>{      public bool CompareTo(string other){         ...      }}
D. public class Person : IComparable<string>{      public bool CompareTo(object other){         ...      }}
Answer: A 
 
 
 

免责声明:文章转载自《C#笔记25:比较和排序(IComparable和IComparer以及它们的泛型实现)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Zabbix 监控主机加强版猜年龄游戏。下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

php:// 访问各个输入/输出流

相关 php.ini 配置 allow_url_fopen :on 默认开启 该选项为on便是激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象文件等。 allow_url_include:off 默认关闭,该选项为on便是允许 包含URL 对象文件等 php://stdin, php://stdout 和 php://stderr...

使用webpack搭建vue开发环境

最近几天项目上使用了vue.js作为一个主要的开发框架,并且为了发布的方便搭配了webpack一起使用。CSS框架使用的是vue-strap(vue 对bootstrap控件做了封装)这篇文章主要总结一下具体搭建的过程,和途中遇到的一些问题的解决办法 主要用到的工具 Vue webpack vue-strap vue-router 搭建步骤 1. 首先...

WPF ListBox CheckBox 里面如何添加字段进行显示

                                                             <Grid DockPanel.Dock="Top" Height="300"> <DockPanel> <Grid DockPanel.Dock="Left" Margin="180,0,0,0">...

两三栏布局

一、背景 在日常布局中,无论是两栏布局还是三栏布局,使用的频率都非常高 PS: 文末有彩蛋 两栏布局 两栏布局实现效果就是将页面分割成左右宽度不等的两列,宽度较小的列设置为固定宽度,剩余宽度由另一列撑满, 比如 Ant Design 文档,蓝色区域为主要内容布局容器,侧边栏为次要内容布局容器 ❝ 这里称宽度较小的列父元素为次要布局容器,宽度较大的列父元素为...

iOS 后台运行实现

iOS 后台运行的规则 应用的运行状态分为以下五种:Not running:应用还没有启动,或者应用正在运行但是途中被系统停止。Inactive:当前应用正在前台运行,但是并不接收事件(当前或许正在执行其它代码)。一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或者系统提示用户...

WPF XAML 特殊字符(小于号、大于号、引号、&amp;amp;符号)

    XAML 受限于 XML 规则。例如, XML 特别关注一些特殊字符,如  & < > 如果试图使用这些字符设置一个元素内容,将会遇到许多麻烦,因为 XAML 解析器认为您正在做其他的事情——例如,创建一个嵌套元素。     例如,假设需要创建一个包含<Click Me>文本的按钮。下面的标记是不能完成这一工作的:...