目录
使用 IEnumerable 和 IEnumerator 接口来使某个类成为可枚举类型 340P
枚举器 和 可枚举类型 (336P)
- 每一个可枚举的类型都有一个 GetEnumerator 方法,对于有枚举器的类型而言, 获取一个对象的枚举器的方法是调用对象的 GetEnumerator 方法。实现 GetEnumerator 方法的类型称为可枚举类型。数组就是可枚举类型。
下图演示了可枚举类型和枚举器之间的关系:
namespace HelloWorld_Console { class Program { static void Main(string[] args) { int[] MyArray = { 10, 11, 12, 13, 45, 77, 66 }; // 数组是可枚举类型,那么该语句调用的是数组中的 GetEnumerator()方法,来获取枚举器 IEnumerator ie = MyArray.GetEnumerator(); while(ie.MoveNext()) // 从当前的有效位置移到下一位置 { int i = (int)ie.Current; // 获取当前位置的元素 Write($"{i},"); } } } }
IEnumerator 接口 (337P)
如果一个 枚举器它实现 IEnumerator接口,那么该接口将包含三个函数成员:
- Current, MoveNext, and Reset。
下图中 枚举器是一个叫做 ArrEnumerator 类的实例:
IEnumerable 接口
如果一个类实现了 IEnumerable 接口 , 那么就称为该类是可枚举类 或者是称该类是 可枚举类型的。 该接口只存在唯一的方法 GetEnumerator , 那么该方法可以返回可以枚举类型的枚举器。
使用 IEnumerable 和 IEnumerator 接口来使某个类成为可枚举类型 340P
namespace HelloWorld_Console
{
class ColorEnumerator : IEnumerator
{
string[] colors;
int position = -1; // 枚举器的起始位置,在第一个元素之前
public ColorEnumerator(string [] theColors)
{
colors = new string[theColors.Length];
for(int i=0;i<theColors.Length;++i)
{
colors[i] = theColors[i];
}
}
public object Current
{
get
{
if(position == -1) // 如果枚举器当前的位置是第一个元素之前的位置
{
throw new InvalidOperationException();
}
if(position >= colors.Length) // 如果枚举器的位置已在最后一个元素之后的位置
{
throw new InvalidOperationException();
}
return colors[position]; // 返回当前位置的元素
}
}
public bool MoveNext()
{
if(position < colors.Length -1) // 如果当前的 position 在数组的正确范围内
{
++position;
return true;
}
return false;
}
public void Reset()
{
position = -1; // 重置枚举器的位置,到第一个元素之前
}
}
class Spectrum : IEnumerable
{
string[] Colors = { "violet", "blue", "cyan", "green", "yellow", "orange", "red" };
public IEnumerator GetEnumerator() // 获取一个枚举器
{
return new ColorEnumerator(Colors);
}
}
class Program
{
static void Main(string[] args)
{
Spectrum spectrum = new Spectrum();
foreach(string tt in spectrum)
{
Write($"{tt},");
}
}
}
}
迭代器块(341P)
迭代器块是带有一个或多个yield语句的代码块。以下 三种代码块 都可以是迭代器块:
- 方法主体
- 访问器主体
- 运算符主体
迭代器块有两个特殊语句:
- yield return语句指定要返回的序列中的下一项。
- yield break语句指定序列中没有更多的项。
可以根据迭代器块的返回类型, 你可以让迭代器产生枚举器或可枚举类型:
使用迭代器来创建枚举器 (344P)
namespace HelloWorld_Console
{
class MyClass
{
public IEnumerator<string> GetEnumerator()
{
return BlackAndWhite(); // 返回枚举器
}
public IEnumerator<string> BlackAndWhite() // 迭代器
{
yield return "black";
yield return "gray";
yield return "white";
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
foreach(string tt in mc)
{
WriteLine(tt);
}
}
}
}
使用迭代器来创建可枚举类型 (346)
namespace HelloWorld_Console
{
class MyClass
{
public IEnumerator<string> GetEnumerator()
{
IEnumerable<string> myEnumerable = BlackAndWhite();
return myEnumerable.GetEnumerator();
}
public IEnumerable<string> BlackAndWhite()
{
yield return "black";
yield return "gray";
yield return "white";
}
}
class Program
{
static void Main(string[] args)
{
MyClass mc = new MyClass();
foreach (string shade in mc)
Console.Write("{0} ", shade);
foreach (string shade in mc.BlackAndWhite())
Console.Write("{0} ", shade);
}
}
}