集合的枚举和排序

送分小仙女□ 提交于 2020-01-19 08:49:06

原文

实现了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属性不同:

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!