• c#中Iterator的实现和其他


    原文地址在这里
    虽然是很老的文章,但是这个博客内容里,有很多很有用的内容。

    前言

    迭代器,Iterator很多语言中都有的概念,对应C#中比如IEnumerable类。

    C#中的Iterator是一个复杂的语法糖,在定义一个Iterator时,一般通过一个含有yield return的函数来实现。

    这背后的思想是,这个Iterator以及和它有关的变量,都被编译器封装在了一个Helper类中,在这个Helper类中,还会维护一个State状态变量,维护当前Iterator上次使用的状态。

    说明

    比如如下代码中,CountFrom返回一个从startlimit的int型iterator。

    class MyClass {
        int limit = 0;
        public MyClass(int limit) {
            this.limit = limit;
        }
        public IEnumerable<int> CountFrom(int start)
        {
            for (int i = start; i <= limit; i++) {
                yield
                return i;
            }
        }
    }
    

    编译器会将CountFrom转换为一个Helper类,而其内部有一个状态机:

     class MyClass_Enumerator: IEnumerable < int > {
         int state$0 = 0; // internal member
         int current$0; // internal member
         MyClass this$0; // implicit parameter to CountFrom
         int start; // explicit parameter to CountFrom
         int i; // local variable of CountFrom
         public int Current {
             get {
                 return current$0;
             }
         }
         public bool MoveNext()
         {
             switch (state$0) {
                 case 0:
                     goto resume$0;
                 case 1:
                     goto resume$1;
                 case 2:
                     return false;
             }
             resume$0: ;
             for (i = start; i <= this$0.limit; i++) {
                 current$0 = i;
                 state$0 = 1;
                 return true;
                 resume$1: ;
             }
             state$0 = 2;
             return false;
         }
         ......
         下面还有一些在这里无关紧要的代码…
     }
     public IEnumerable<int> CountFrom(int start)
     {
         MyClass_Enumerator e = new MyClass_Enumerator();
         e.this$0 = this;
         e.start = start;
         return e;
     }
    

    其中:

    • start$0,current$0是内部变量维护
    • starti是实际遍历使用的变量
    • state$0resume$0/1/..维护了当前iterator的执行状态,有执行过程中,执行开始,执行结束
      • 这里如果原iterator有多个yield return,那么相应的状态result$n也会增加

    实际的逻辑,就写在MyClass_Enumerator类的MoveNext中,每次向前取值后,通过Current返回当前值。
    下次再次进入时,由于内部类保证了状态,可以从上一次开始继续取值。

    这种内部类的方法,相比较递归方式,更节省栈空间,因为类是分配在堆上的。

    其他补充

    这种通过yield return+状态机的思想,也是后面c#异步编程async await等的一种思想。
    通过一个helper类,记录之前的状态,下次进入直接从之前的状态执行

  • 相关阅读:
    实用的css3小实例---1、卡片效果
    CSS3疑难问题---1、px、em、rem的区别
    心得体悟帖---200106(录课本质)(工具人)
    心得体悟帖---200105(心性不够容易失去)
    心得体悟帖---200105(legend3做好升段)(还不够厉害)
    心得体悟帖---200104(每天运动)(危急存亡)
    webstorm2019.2永久破解教程(亲测有效)
    范仁义css3课程---6、文本样式1
    范仁义css3课程---7、文本2(css3文本)
    css文本样式总结
  • 原文地址:https://www.cnblogs.com/mosakashaka/p/12804832.html
Copyright © 2020-2023  润新知