泛型的概念--“通过参数化类型来实现在同一份代码上操作多种数据类型。利用“参数化类型”将类型抽象化,从而实现灵活的复用”
BubbleSort定义成泛型类 定义泛型类的一种方法是在类后面加上“<T>”
//定义泛型类SortHelper 这里“where T:IComparable” 是给类型参数T一个限制 -- 参数类型必须实现IComparable接口,否则无法通过编译
public class SortHelper<T> where T:IComparable
{
public void BubbleSort(T[] arr)
{
int length = arr.Length;
for (int i = 0; i < length-1; i++)
{
for (int j = 0; j < length-1-i; j++)
{
if (arr[j].CompareTo(arr[j+1])>0)
{
T temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
}
public class cat:IComparable
{
public string name;
public int price;
public int CompareTo(object obj)
{
cat catT = (cat)obj;
return this.price.CompareTo(catT.price);
}
public cat(string name, int price)
{
this.price = price;
this.name = name;
}
}
static void Main(string[] args)
{
SortHelper<byte> sorter = new SortHelper<byte>();
byte[] a = { 4,5,1,3,2,8,5,0,2};
sorter.BubbleSort(a);
SortHelper<int> sorter1 = new SortHelper<int>();
int[] b = { 4, 5, 1, 3, 2, 8, 5, 0, 2 };
sorter1.BubbleSort(b);
SortHelper<cat> sorter2 = new SortHelper<cat>(); cat cat1=new cat("猫1",1000); cat cat2=new cat("猫2",1400); cat cat3=new cat("猫3",400); cat[] c = { cat1, cat2, cat3 }; sorter2.BubbleSort(c);
//输出省略 }
IEnumerable<T>接口的IEnumerator<T> GetEnumerator()方法返回了一个迭代器 ,不难发现T如果用 out 标记,则T代表了输出,也就说只能作为结果返回。
IComparable<T>接口的CompareTo(T other)方法传入了一个T类型的Other参数,不难发现T如果用 in 标记,则T代表了输入,也就是它只能作为参数传入。
为了在foreach中使用 People的实例, 我们给People实现IEnumerable接口,代码如下:
public class People:IEnumerable { private Person[] _people; public People(Person[] pArray) { //实例化数组 用于存Person实例 _people = new Person[pArray.Length]; for (int i = 0; i < pArray.Length; i++) { _people[i] = pArray[i]; } } ////IEnumerable和IEnumerator通过IEnumerable的GetEnumerator()方法建立了连接,可以通过IEnumerable的GetEnumerator()得到IEnumerator对象。 IEnumerator IEnumerable.GetEnumerator() { return (IEnumerator)GetEnumerator(); } public PeopleEnum GetEnumerator() { return new PeopleEnum(_people); } } public class PeopleEnum:IEnumerator { public Person[] _people; public PeopleEnum(Person [] pArray) { _people = pArray; } //游标 int position = -1; //是否可以往下 移 public bool MoveNext() { position++; return (position < _people.Length); } //集合的所有元素取完了之后 重置position public void Reset() { position = -1; } //实现 IEnumerator的 Current方法 返回当前所指的Person对象 object IEnumerator.Current { get { return Current; } } //Current是返回Person类实例的只读方法 public Person Current { get { try { return _people[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } }
static void Main(string[] args) { Person[] personArray = new Person[3]{ new Person("Keiling1"), new Person("Keiling2"), new Person("Keiling3"), }; People people = new People(personArray); foreach (Person item in people) { Console.WriteLine(item.name); } }
1.一个集合要支持foreach方式的遍历,必须实现IEnumerable接口,描述这类实现了该接口的对象,我们叫它 ‘序列’。
比如 List<T> 支持 foreach 遍历 是因为它实现了IEnumerable接口和其泛型版,
2. IEnumerator对象具体实现了迭代器(通过MoveNext(),Reset(),Current)。
3. 从这两个接口的用词选择上,也可以看出其不同:IEnumerable是一个声明式的接口,声明实现该接口的class是“可枚举(enumerable)”的,但并没有说明如何实现迭代器,
而IEnumerator是一个实现式的接口,IEnumerator对象就是一个迭代器。
4.由于IEnumerable<T>继承了IEnumerable接口,所以要实现IEnumerator<T> ,还需要实现IEnumerator接口,由于和泛型版本的方法同名,所以该方法的实现需要使用显式接口实现。这里就不继续介绍它的具体实现了,和IEnumerator基本一致,这里就不详述了,读者可以自己动手写一下。