C# 2.0 新迭代器分析

来源:互联网 发布:圆珠笔 知乎 编辑:程序博客网 时间:2024/06/01 09:06
# 2.0引入了很多方便程序员的新功能,其中迭代器是一个
.Net Reflector真是个好东西,为了分析新的迭代器,我用到了它来反编译程序以了解.NET内部的迭代机制.
源程序很简单,用到了的新的迭代器的一种新用法,还有其他几种用法,但是此文只分析迭代器,所以其他的就不举例了.
另外程序中用到了泛型(Generic),这也是C#2.0的特性,.
class Program
    {
//创建一个静态迭代器,使用System.Collections.Generic命名空间中的泛型IEnumerable接口并用Int实例化.
    static IEnumerable<int> FromTo(int from, int to)    
    {
        while (from <= to)
        {
            yield return from++;
//yield return是一个新的关键字,意义在下面做分析
        }
    }
        static void Main(string[] args)
        {
            foreach (int i in FromTo(5, 10))
            {
                Console.WriteLine(i); 
//这个foreach使用前面那个FromTo输出5到10的几个数字
            }
        }
    }
}
用Reflector反编译Program类得:
主函数:
private static void Main(string[] args){      using (IEnumerator<int> enumerator1 = Program.FromTo(5, 10).GetEnumerator())      {            while (enumerator1.MoveNext())            {                  int num1 = enumerator1.Current;                  Console.WriteLine(num1);            }      }}

源程序中关于迭代器的代码则被编译成了:

private static IEnumerable<int> FromTo(int from, int to){      Program.<FromTo>d__0 d__1 = new Program.<FromTo>d__0(-2);      d__1.<>3__from = from;      d__1.<>3__to = to;      return d__1;}

 

FromTo返回了一个类,这个类反编译的代码是:

[CompilerGenerated]
private sealed class <FromTo>d__0 :
IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable
{
      // Methods
      [
DebuggerHidden]
      public <FromTo>d__0(
int <>1__state);
      private
bool MoveNext();
      [
DebuggerHidden]
     
IEnumerator<int> IEnumerable<int>.GetEnumerator();
      [
DebuggerHidden]
     
IEnumerator IEnumerable.GetEnumerator();
      [
DebuggerHidden]
     
void IEnumerator.Reset();
     
void IDisposable.Dispose();

      // Properties
     
int IEnumerator<int>.Current { [DebuggerHidden] get; }
     
object IEnumerator.Current { [DebuggerHidden] get; }

      // Fields
      private
int <>1__state;
      private
int <>2__current;
      public
int <>3__from;
      public
int <>3__to;
      public
int from;
      public
int to;
}

类中GetEnumerator方法的代码为:

IEnumerator<int> IEnumerable<int>.GetEnumerator()
{
     
Program.<FromTo>d__0 d__1;
      if (
Interlocked.CompareExchange(ref this.<>1__state, 0, -2) == -2)
      {
           
d__1 = this;
      }
      else
      {
           
d__1 = new Program.<FromTo>d__0(0);
      }
     
d__1.from = this.<>3__from;
     
d__1.to = this.<>3__to;
      return
d__1;
}
Interlocked.CompareExchange(ref this.<>1__state, 0, -2) == -2是比较当前state(状态)是否为-2,如果为-2则替换为0.

GetEnumerator的作用是得到一个初始化了得迭代器实例,状态代码(state)为0.

然后就是MoveNext方法:

private bool MoveNext()
{
      switch (this.
<>1__state)
      {
            case 0:
            {
                  this.
<>1__state = -1;
                  while (this.
from <= this.to)
                  {
                        this.
<>2__current = this.from++;
                        this.
<>1__state = 1;
                        return true;
                  Label_004A:
                        this.
<>1__state = -1;
                  }
                  break;
            }
            case 1:
            {
                  goto Label_004A;
            }
      }
      return false;
}
每次执行MoveNext会改变迭代器中的Current量.

而yield return就是在每次MoveNext后返回迭代器中的Current