zoukankan      html  css  js  c++  java
  • 迭代器

    http://www.kingreatwill.com/

    (1)使用

          我们每次针对集合类型编写foreach代码块,都是在使用迭代器

          这些集合类型都实现了IEnumerable接口

          都有一个GetEnumerator方法

          但对于数组类型就不是这样

          编译器把针对数组类型的foreach代码块

          替换成了for代码块。

          来看看List的类型签名:    

          public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable

          IEnumerable接口,只定义了一个方法就是:    

          IEnumerator<T> GetEnumerator();

        (2)迭代器的优点:

          假设我们需要遍历一个庞大的集合

          只要集合中的某一个元素满足条件

          就完成了任务

          你认为需要把这个庞大的集合全部加载到内存中来吗?

          当然不用(C#3.0之后就不用了)!

          来看看这段代码:      

    复制代码
            static IEnumerable<int> GetIterator()
            {
                Console.WriteLine("迭代器返回了1");
                yield return 1;
                Console.WriteLine("迭代器返回了2");
                yield return 2;
                Console.WriteLine("迭代器返回了3");
                yield return 3;
            }
    复制代码

          消费这个函数的代码如下:      

    复制代码
                foreach (var i in GetIterator())
                {
                    if (i == 2)
                    {
                        break;
                    }
                    Console.WriteLine(i);
                }
                Console.ReadKey();
    复制代码

          输出结果为:      

          迭代器返回了1
          1
          迭代器返回了2

          大家可以看到:

          当迭代器返回2之后,foreach就退出了

          并没有输出“迭代器返回了3”

          也就是说下面的工作没有做。

        (3)yield 关键字

          MSDN中的解释如下:

          在迭代器块中用于向枚举数对象提供值或发出迭代结束信号。

          也就是说,我们可以在生成迭代器的时候,来确定什么时候终结迭代逻辑

          上面的代码可以改成如下形式:      

    复制代码
              static IEnumerable<int> GetIterator()
              {
                  Console.WriteLine("迭代器返回了1");
                  yield return 1;
                  Console.WriteLine("迭代器返回了2");
                  yield break;
                  Console.WriteLine("迭代器返回了3");
                  yield return 3;
              }
    复制代码

         (4)注意事项

          <1>做foreach循环时多考虑线程安全性      

            在foreach时不要试图对被遍历的集合进行remove和add等操作

            任何集合,即使被标记为线程安全的,在foreach的时候,增加项和移除项的操作都会导致异常

            (我在这里犯过错)

          <2>IEnumerable接口是LINQ特性的核心接口

            只有实现了IEnumerable接口的集合

            才能执行相关的LINQ操作,比如select,where等

            这些操作,我们接下来会讲到。

    http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.html

    我们再看看微软的例子:https://msdn.microsoft.com/zh-cn/library/9k7k7cf0(v=vs.80).aspx

    迭代器块中用于向枚举数对象提供值或发出迭代结束信号。它的形式为下列之一:

     
     
    yield return <expression>;
    yield break;
    
    备注
     

    计算表达式并以枚举数对象值的形式返回;expression 必须可以隐式转换为迭代器的 yield 类型。

    yield 语句只能出现在 iterator 块中,该块可用作方法、运算符或访问器的体。这类方法、运算符或访问器的体受以下约束的控制:

    • 不允许不安全块。

    • 方法、运算符或访问器的参数不能是 ref 或 out

    yield 语句不能出现在匿名方法中。有关更多信息,请参见匿名方法(C# 编程指南)

    当和 expression 一起使用时,yield return 语句不能出现在 catch 块中或含有一个或多个 catch 子句的 try 块中。有关更多信息,请参见异常处理语句(C# 参考)

    示例
     

    在下面的示例中,迭代器块(这里是方法 Power(int number, int power))中使用了 yield 语句。当调用 Power 方法时,它返回一个包含数字幂的可枚举对象。注意 Power 方法的返回类型是 IEnumerable(一种迭代器接口类型)。

     
     
    // yield-example.cs
    using System;
    using System.Collections;
    public class List
    {
        public static IEnumerable Power(int number, int exponent)
        {
            int counter = 0;
            int result = 1;
            while (counter++ < exponent)
            {
                result = result * number;
                yield return result;
            }
        }
    
        static void Main()
        {
            // Display powers of 2 up to the exponent 8:
            foreach (int i in Power(2, 8))
            {
                Console.Write("{0} ", i);
            }
        }
    }
    

    输出

    2 4 8 16 32 64 128 256 

  • 相关阅读:
    Maxwell的vbs脚本转matlab
    maxwell电机直观理解
    maxwell电机转矩扫描与使用MTPA策略绘制效率map图
    maxwell施加均匀外磁场
    maxwell的那些坑&小技巧
    maxwell主从边界
    MySql基础
    数据结构知识结构框架图
    第八章 多线程
    软件
  • 原文地址:https://www.cnblogs.com/kingreatwill/p/4364967.html
Copyright © 2011-2022 走看看