数组和集合接口:
Array类实现了IEumerable,ICollection和IList接口,以访问和枚举数组中的元素。由于用定制数组创建的类派生于Array抽象类,所以能使用通过数组变量执行的接口中的方法和属性。(下划线内容注解:所以能通过数组变量使用上述接口中的方法和属性)
IEumerable是由foreach语句用于迭代数组的接口。其定义了GetEnumerator()方法。
ICollection接口派生于IEumerable接口,并添加属性如Count,IsSynchronized,方法如CopyTo()
IList接口派生于ICollection接口,并添加了属性如:IsFixedSize(数组大小是否固定)、IsReadOnly(数组是否只读)、Item(可以用整型索引访问数组);方法:Add、Clear、Contains(线性搜索是否包含某个元素)、IndexOf、Insert、Remove、RemoveAt。
Array类实现IList接口,并使用了IList接口中的Item属性,以使用索引器访问元素。IList接口的许多其他成员是通过Array类抛出NotSupportedException异常实现的,因为他们不应用于数组。
枚举
在foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中元素的个数。
数组或集合执行带GetEnumerator()方法的IEnumerable接口。GetEnumerator()方法返回一个执行IEumerable接口的枚举。接着,foreach语句就可以使用IEumerable接口迭代集合了。
GetEnumerator()方法用IEnumerable接口定义。Foreach语句并不真的需要在集合类中执行这个接口(集合类中可以不需要继承IEnumerable接口)。只要有一个名为GetEnumerator方法返回实现了IEnumerator接口的对象就足够了。
注意:
IEnumerable接口和IEnumerator区别
IEnumerable接口定义GetEnumerator方法
IEnumerator接口:
Foreach语句使用IEnumerator接口的方法和属性,迭代集合中的所有元素。成员如下:
MoveNext()方法移动到集合的下一个元素上,如果有这个元素返回ture,否则返回false
Current属性返回光标所在的元素。
Reset()方法将光标重新定位于集合的开头。
Foreach语句:
C#的foreach语句不会解析为IL代码中的foreach语句。C#编译器会把foreach语句转换为IEnumerator接口的方法和属性。如下示例:
Foreach语句:
Foreach(Person p in persons)
{Console.WriteLine(p);}
C#编译器转换后:
IEnumerator enumerator=persons.GetEnumerator();//调用GetEnumerator方法获取数组枚举
While(Enumerator.MoveNext())//使用MoveNext方法
{ Person p=(Person)enumerator.Current;//用Current访问数组中的元素
Console.WriteLine(p);}
Yield语句
Yield return语句返回集合的一个元素,并移动到下一个元素上。Yield break可停止迭代。
包含yield语句的方法或属性也称为迭代块。迭代块必须声明为返回IEnumerator或IEnumerable接口。这个块可以包含多个yield return或yield break语句,但不能包含return语句。
Yield语句其实是把元素返回到一个IEnumerator容器中,当返回执行完所有的yield语句后,foreach语句使用这个IEnumerator的方法和属性迭代元素。其中数组或集合类通过调用GetEnumerator方法获取数组枚举,如Foreach(Person p in persons),直接使用实例化对象persons情况下会默认调用GeEnumerator方法。否则应该显示调用含有yield语句的方法。如:Foreach(Person p in persons.Reveres())//其中Reveres()方法中含有yield语句
使用迭代块,编译器会生成一个yield类型,其中包含一个状态机。如下代码:
public class HelloCollection
{
public IEnumerator GetEnumerator()
{
//yield return "Hello";
//yield return "World";
Enumerator enumerator = new Enumerator(0);
return enumerator;
}
public class Enumerator : IEnumerator, IDisposable
{
private int state;
private object current;
public Enumerator(int state)
{
this.state = state;
}
bool System.Collections.IEnumerator.MoveNext()
{
switch (state)
{
case 0:
current = "Hello";
state = 1;
return true;
case 1:
current = "World";
state = 2;
return true;
case 2:
break;
}
return false;
}
void System.Collections.IEnumerator.Reset()
{
throw new NotSupportedException();
}
object System.Collections.IEnumerator.Current
{
get
{
return current;
}
}
void IDisposable.Dispose()
{
}
}
}
高级应用:yield返回枚举器。