惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
量子位
GbyAI
GbyAI
腾讯CDC
T
Tailwind CSS Blog
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
D
Docker
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
The GitHub Blog
The GitHub Blog
Microsoft Security Blog
Microsoft Security Blog
Stack Overflow Blog
Stack Overflow Blog
Hugging Face - Blog
Hugging Face - Blog
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
N
Netflix TechBlog - Medium
Jina AI
Jina AI
IT之家
IT之家
Y
Y Combinator Blog

博客园 - JustRun

Webpack中publicPath设置 忘记Mysql的root密码怎么办? Visual Studio 2015上安装Entity Framework Power Tools Ubuntu下安装中文输入法 Ubuntu如何选择更新源 Orchard中如何配置远端发布 .Net缓存管理框架CacheManager 全新的membership框架Asp.net Identity(2)——绕不过的Claims 全新的membership框架Asp.net Identity(1)——.Net membership的历史 泛型使用中,解决类型转换问题 .Net中使用SendGrid Web Api发送邮件(附源码) 使用Filter跟踪Asp.net MVC页面加载时间 下一代Asp.net开发规范OWIN(3)—— Middleware 下一代Asp.net开发规范OWIN(2)—— Katana介绍以及使用 下一代Asp.net开发规范OWIN(1)—— OWIN产生的背景以及简单介绍 对象映射工具AutoMapper介绍 AngularJs中,如何在render完成之后,执行Js脚本 代替Reflection(反射)的一些方法 使用PhoneGap开启移动开发之旅
.Net Collection的一些理解——记录一次向实习生的答疑
JustRun · 2014-08-14 · via 博客园 - JustRun

2014-08-14 12:18  JustRun  阅读(2997)  评论()    收藏  举报

公司最近进了个实习生,每天下班前我都会花一些时间来解答一下实习生的一些疑问。今天问起了关于集合排序方法Sort的一些疑问,这让我一下回到自己刚刚入行的时候。那个时候也遇到了集合排序的问题,为发现接口IComparableICompare的妙处而兴奋,还在公司的内部分享会上分享了如何使用它们来排序。现在经过多年的开发实践以及学习,对于同一个问题又有了更加深入的理解。

一. 为什么说”实现了IEnumerable接口才能遍历”

实习生先是问了这个问题, 其实这个问题, 非常容易解答.
先来看看IEnumerable接口的定义:

public interface IEnumerable
{
    IEnumerator GetEnumerator();
}

这个接口非常简单,主要就是一个方法GetEnumerator,用来返回一个IEnumerator对象。
继续深入下去,IEnumerator接口的定义如下:

public interface IEnumerator
{
   bool MoveNext();
      void Reset();
     object Current {  get; }
}

上面的IEnumerator接口定义的属性和方法,只有一个目的,就是实现如何遍历。下面具体解释一下:

  • Current属性, 用来返回当前集合项的值
  • MoveNext方法, 移动到集合对象的下一项,如果有下一项,就返回true, 如果没有,就返回false.
  • Reset(), 重置然后可以重头访问集合

到这里,为什么foreach能够遍历集合对象的原因就是因为集合对象都实现了IEnumerable接口,提供了具体的实现来遍历集合对象。

二. Sort()方法以及IComparable、IComparer接口

集合类型,都有Sort()排序方法,这个函数的一个重载版本中,需要提供一个IComparer类型的接口。为什么需要使用这个接口呢?这个和排序有什么关系?
想一想,实现排序必须的是什么?必须的是能够比较大小。对于int, string这种.Net内部类型,本身已经支持了IComparer, 也就是可以比较大小了。但是对于我们自己定义的类型,使用Sort方法是无法排序的,因为程序不知道我们对于自定义对象的排序规则, 这个时候就可以使用IComparableIComparer.

下面举一个实际的例子, 这里我们自定义了一个类Car, 然后对Car的集合进行排序.

public class Car
{
       public string Name { get; set; }
       public int Year { get; set; }
       public int Seats { get; set; }
}

假如我们直接调用Sort方法, 就会悲剧抛出InvalidOperationException异常

image 

2.1 IComparable接口

IComparable 接口提供了比较某个特定类型对象的方法. 这里来说, 我们要让Car实现IComparable 接口来达到比较Car对象的目的,从而实现排序。实现IComparable接口, 就必须实现CompareTo 方法, 具体如下:

public class Car: IComparable
{
       public string Name { get; set; }
       public int Year { get; set; }
       public int Seats { get; set; }

       public int CompareTo(object obj)
       {
           var car = (Car) obj;
           return String.CompareOrdinal(Name, car.Name);
       }
}

上面我们的Car对象实现了IComparable接口,按照Name字符串属性来比较. 直接运行Sort()方法,就能够得到排序结果:

image

2.2 IComparer接口

IComparer接口可以提供更加丰富和灵活的排序功能。 比如, 你可能需要在不同的场合,根据不同的属性来排序.
下面就来实现一个根据Car的Year属性来排序, 首先创建类CarYearComparer来对Car进行比较,比较是根据Year属性

public class CarYearComparer: IComparer<Car>
{
       public int Compare(Car x,  Car y)
       {
           if (x.Year > y.Year)
               return 1;
           if (x.Year < y.Year)
               return -1;
           return 0;
       }
}

在调用Sort方法排序的时候,需要指定使用的IComparer实现:

cars.Sort(new CarYearComparer());

得到的排序结果和上面的根据Name属性不同:

image

还可以实现一个根据Car的属性Seats排序的IComparer. 所以使用IComparer更加的灵活

3. 面向对象设计思想

Collection中的Sort()方法很好地遵循了开放封闭原则,既很好地完成了排序的功能,同时又开放出了入口,让你可以为排序自定义规则。

下面是我个人的一些个人理解:
一个类应该做自己擅长的事情和核心的事情(单一职责),把不擅长的交给别人。但是这个”别人“是不是任何人都可以呢?当然不是,为了更好的限定别人,我们使用了接口限定。
当一个类依赖于抽象(也就是接口),那么这个类的适用范围就更加广,就能够更加超脱。老子一句”道可道,非常道;名可名,非常名”,正是没有具体化,所以可以解释万物。

更多的面向对象设计原则,参照http://www.360doc.com/content/11/0521/00/3554006_118258005.shtml

最后附上本文相关源代码: SortDemo

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下右下角的关注 Justrun
因为,我的写作热情也离不开您的肯定支持。

感谢您的阅读,这里还有你可能感兴趣的文章推荐博客文章