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