zoukankan      html  css  js  c++  java
  • C# 关于"yield return"的研究(转载)

    转载自:http://hi.baidu.com/algorithmanlxl/item/d94211d17a831c2039f6f792

    这里的研究是借助了http://jangmon.blogbus.com/logs/36380490.html的帮助,虽然其中有些代码出现了错误,而且颇多细节没说清楚,但是对鄙人的启发意义很大。各位可以去该链接学习一下。而事实上,由于C#在.net框架中的高级特性和技术内幕很难深层次的说清楚,有些东西鄙人也是不甚明了。具体的接口说明和解释可以看看上面那篇博文,在这里我是想说说困扰很多人的"yield return”问题,到底其作用是怎么发挥的?我是用单步调试将其大概的调用顺序摸清楚的。先给出源程序,诸君可将其复制建立工程然后对比。

    class Program
    {
        static void Main(string[] args)
        {
            HelloCollection helloCollection = new HelloCollection();
            foreach (string s in helloCollection)
                Console.WriteLine(s);
    
            Console.ReadKey();
        }
    
        //public class HelloCollection : IEnumerable
        //{
        //    public IEnumerator GetEnumerator()
        //    {
        //        yield return "Hello";
        //        yield return "World";
        //    }
        //}
        public class HelloCollection : IEnumerable
        {
            public IEnumerator GetEnumerator()
            {
                Enumerator enumerator = new Enumerator(0);
                return enumerator;
            }
            public class Enumerator : IEnumerator, IDisposable
            {
                private int state;
                private object current;
                public Enumerator(int state)
                {
                    this.state = state;
                }
                public bool MoveNext()
                {
                    switch (state)
                    {
                        case 0:
                            current = "Hello";
                            state = 1;
                            return true;
                        case 1:
                            current = "World";
                            state = 2;
                            return true;
                        case 2:
                            break;
                    }
                    return false;
                }
                public void Reset()
                {
                    throw new NotSupportedException();
                }
                public object Current
                {
                    get { return current; }
                }
                public void Dispose()
                {
                }
            }
        }
    }

    上面注释的部分引用了"yield return”,其功能相当于下面所有代码!为什么呢,其实要从底层来说也很难解释得清楚,大家可以在foreach之前设一个断点,然后调试运行,会发现断点运行到foreach那一行的时候,会先编译"helloCollection",然后跳到下面的public IEnumerator GetEnumerator()执行该函数,而函数中原本的yield return会为HelloCollection类自动生成代码,就是多了Enumerator这个内部类的实现,且public IEnumerator GetEnumerator()里面的代码也会变成

    Enumerator enumerator = new Enumerator(0);
                return enumerator;

    那么在运行到Enumerator enumerator = new Enumerator(0);的时候就会发现又跳到了Enumerator内部类的构造函数,构造完成后,回去编译foreach那行的"in",会发现又跳到了MoveNext函数,执行完毕后再去编译foreach那行的"string s”,发现跳到了Current字段的定义,调用了get方法,其内部估计是对s执行了赋值,不确定(暂且这样理解)。以此类推,最后会发现直到执行MoveNext返回了false,那么就会跳到了Dispose(),最后就这样了。

    上面讲述的是通过断点来分析其运行的,而事实上如果比较简洁地去说的话,foreach这一行会被编译成IEnumerator e=helloCollection.GetEnumerator(),并自动生成一个while(e.MoveNext())循环实现了整个聚合的遍历。

    本文转载自:http://hi.baidu.com/algorithmanlxl/item/d94211d17a831c2039f6f792

  • 相关阅读:
    组装树状结构文本框
    在jsp页面动态添加,删除文本框模块
    sql字段拆分 ,连表子查询获取值
    jsp页面技术总结
    C语言的基本数据类型
    如何学习一些需要算法的程序
    如何学习一门新的编程语言
    C++ 预处理器
    C++ 函数模板&类模板
    C++ 文件和流
  • 原文地址:https://www.cnblogs.com/icyJ/p/yield.html
Copyright © 2011-2022 走看看