C# 2.0 新迭代器分析

来源:互联网 发布:大陆网络公知大v 编辑:程序博客网 时间:2024/06/07 16:53
//by DaH, Feb 1,2006
C# 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

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 吃母乳的宝宝不爱喝水怎么办 三个月宝宝不肯吃奶粉怎么办 三个月宝宝不肯喝奶粉怎么办 三个月的宝宝不肯喝奶粉怎么办 三个月的宝宝不肯吃奶粉怎么办 饿了还是没食欲怎么办 3岁半幼儿便秘怎么办 小孩字写得难看怎么办 小孩的字写的丑怎么办 小孩字写的太差怎么办 小孩很多字不会写怎么办 食欲不好吃不多怎么办 中班小孩子子不肯写字怎么办 1岁宝便秘该怎么办 两周的宝宝便秘怎么办 3岁宝宝不肯吃药怎么办 1岁婴儿不肯吃药怎么办 9月婴儿不肯吃药怎么办 半岁宝宝不吃药怎么办 1岁宝宝不爱吃药怎么办 2岁吃多了呕吐怎么办啊 小孩吃撑了吐怎么办 三岁宝宝吃太多怎么办 小孩吃撑发烧了怎么办 婆婆不帮忙带孩子怎么办 孩子在中班幼儿园不爱写字怎么办 小孩不愿意上学不愿意写字怎么办 宝妈太内向不喜欢带孩子出门怎么办 宝宝吃饭不带围兜怎么办 宝宝吃饭不喜欢带围兜怎么办 宝宝吃饭不爱带围兜怎么办 孩子不吃肉和菜怎么办 我很恶心我婆婆怎么办 坐月子不喜欢婆婆抱宝宝怎么办 宝宝一写字就哭怎么办 4岁宝宝不爱学习怎么办 4岁宝宝不爱写字怎么办 孩子调皮老师不让上学了怎么办 小学生写字握笔握出剪子来怎么办 儿子6岁不会写字怎么办 宝宝在幼儿园不说话怎么办