foreach和yield

1.foreach

foreach无需要知道集合中元素个数就可以迭代集合中的元素,它其实是迭代器模式的一个包装,就语言层面来说,是while的另一种形式。

展开

查看IL代码,先看foreach代码块的IL代码:

展开

再看while代码块的IL代码:

展开

可以看出foreach语句块IL代码与while语句块的IL代码相比,只多了finally部分的资源处理,但循环部分的代码基本没有任何分别。

如果让private class Enumerator 增加IDisposable接口,将while语句块改写为如下:

展开

得到的IL代码将与foreach基本没有区别。

由此可见,foreach是编译器给我们的一个语法糖,它包装了while。

2.yield

在上面的代码中枚举器private class Enumerator 是自己实现了IEnumerator接口中的方法,使用yield语句,可以让编译器自动实现,省去了自己写的麻烦(包含yield语句的方法或属性必须声明为返回IEnumerable IEnumerator ),所以上面的public class People 可以这样写

展开

反编译之后,看IL代码:

这是版本1people类

{F)2KABVS%RLZ51ODZ3F%LW

这是版本2的people类

U1PY(JNW_M%W@I~~953UI@Q[1]

自己写的迭代器类Enumerator和编译器生成的迭代器类<GetEnumerator>d_0相比较,<GetEnumerator>d_0增加了IDisposable接口,另外就是增加了IEnumerator接口的泛型版本的继承。如果愿意,Enumerator也可以实现这两个接口。

 

用yield还可以返回IEnumerable接口类型

展开

该PeopleEven()返回的IEnumerable类<PeopleEven>d_0会自动实现GetEnumerator()方法和IEnumerator接口中的方法。看IL代码:

1_thumb4

PeopleEven()返回的类<PeopleEven>d_0实现了IEnumerable和IEnumerator接口以及它们的泛型版本,还实现了IDisposable接口。因此,可以将这3个接口都实现,将类改写:

展开

看IL代码:

24_thumb6

类People与PeopleEven()返回的类<PeopleEven>d_0基本相同,只是少了两个接口的泛型版本的实现。

由此可见,yield是一个更大的语法糖,它可以自动实现IEnumerable和IEnumberator接口中的方法,自动替我们实现迭代器。

用foreach和yield,可以非常方便地使用迭代模式。

posted @ 2010-12-14 00:24  youngbo  阅读(294)  评论(1)    收藏  举报