[c#]foreach的原理
foreach本质上是迭代的使用,学习过程中发现它和c中的地址定位差不多,也是通过游标的不断移动获取当前所指向的数据。迭代器可以用一种方式,顺序访问集合类型(数组、字典、队列....)元素。
简单演示一下:
有一个接口IThrowable,其下有两个继承类Grenade和Darts;类Hand下有一个数组,其中包含Grenade和Darts。
class Hand:IEnumerable { public IThrowable[] AllObject { get; set; } }
Main中实例化一个Hand对象:
static void Main(string[] args) { Hand hand = new Hand() { AllObject = new IThrowable[2]//可投掷物接口,下有两个类手雷和飞镖 { new Grenade(), new Darts() } }; }
此时我们使用迭代器来获取Hand中的所有对象,所以Main应该是:
static void Main(string[] args) { Hand hand = new Hand() { AllObject = new IThrowable[2]//可投掷物接口,下有两个类手雷和飞镖 { new Grenade(), new Darts() } }; //1.获取迭代器 IEnumerator iterator = hand.GetEnumerator(); //2.移动到下一个元素 while (iterator.MoveNext()) { //3.获取元素 Console.WriteLine(iterator.Current); } Console.ReadKey(); }
到这里就会发现迭代器的使用主要就是在GetEnumerator()这个方法,它的返回值是枚举器,也就是我们所理解的游标。所以在Hand中我们需要实现下它的功能:
class Hand:IEnumerable { public IThrowable[] AllObject { get; set; } //传统写法 public IEnumerator GetEnumerator() { //创建迭代器对象 return new HandEnumerator() { Target = AllObject }; } }
这里的HandEnumerator就是生成一个枚举器所用的迭代器
//传统写法 //类的迭代器,以Hand为例 class HandEnumerator : IEnumerator { public IThrowable[] Target { get; set; } private int index; //获取当前数据 public object Current { get { return Target[index]; } } //移动到下一个数据 public bool MoveNext() { index++; return index <= Target.Length - 1; } //未用到暂时不写 public void Reset() { } }
注意上面所注释的是传统的创建迭代器和使用方法,由于有yield关键字的存在,我们将yield和return结合一下,就可以将代码缩简为:
class Hand:IEnumerable { //优化写法 public IEnumerator GetEnumerator() { /* * 将yield以前的代码分配到MoveNext方法中 * 将return后的数据分配到Current属性中 */ for (int i = 0; i < AllObject.Length; i++) { yield return AllObject[i];//返回数据 退出方法 } } }
这样我们就可以将繁琐的HandEnumerator 一起省去了。
运行测试下:


浙公网安备 33010602011771号