集合的枚举和排序

原文

实现了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循环来访问一个对象的时候,其实是默认的调用了对象里面的GetEnumerator()方法。而该方法就是由IEumerable接口给暴露出来的,所以如果想自定义一个能实现枚举功能的集合类就要先实现一个IEnumerable接口,然后实现里面的GetEnumerator方法。如下所示:

namespace Test 

{ 

     class Program 

    { 

         static  void Main( string[] args) 

        { 

            Garage car =  new Garage(); 

             foreach(Car c  in car) 

            { 

                Console.WriteLine( " {0} is going {1} MPH ", c.Name, c.Age); 

            } 

            Console.ReadKey(); 

        } 

    } 

     public  class Garage:IEnumerable  

    {         

        Car[] carArray =  new Car[ 4];   

         // 在Garage中定义一个Car类型的数组carArray,其实carArray在这里的本质是一个数组字段        

         // 启动时填充一些Car对象         

         public Garage()         

        {             

             // 为数组字段赋值             

            carArray[ 0] =  new Car( " Rusty ",  30);             

            carArray[ 1] =  new Car( " Clunker ",  50);             

            carArray[ 2] =  new Car( " Zippy ",  30);             

            carArray[ 3] =  new Car( " Fred ",  45);         

        } 



         public IEnumerator GetEnumerator() 

        {  

             return  this.carArray.GetEnumerator(); 

        } 

    } 

     public  class Car 

    { 

         public  string Name {  get;  set; } 

         public  int Age {  get;  set; } 

         public Car( string name, int age) 

        { 

            Name = name; 

            Age = age; 

        } 

    } 

}

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

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

 

public class Car

{

     public string Name{get;set;}

     public int Year{get;set;}

     public int Seats{get;set;}   

}

 

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

集合的枚举和排序

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()方法,就能够得到排序结果:

集合的枚举和排序

IComparer接口

IComparer接口可以提供更加丰富和灵活的排序功能,它的实现是一个比较器。比如,你可能需要在不同的场合,根据不同的属性来排序。下面就来实现一个根据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属性不同:

集合的枚举和排序

 

你可能感兴趣的:(排序)