Ruby 2.0有一个新的特性是惰性枚举器,Soi Mort 的博客举了一个例子:可以将下面的代码

File.open(path) {|fp|
fp.each_line. \
select {|line| # 生成了临时数组
/regexp/ =~ line
}. \
each_with_index.map {|line, no| # 生成了临时数组
sprintf("%d: %s\n", no, line)
}. \
first(10).each {|str| # 生成了临时数组
puts(str)
}
}

转换为

File.open(path) {|fp|
fp.each_line.lazy \
select {|line| # 没有临时数组产生
/regexp/ =~ line
}. \
each_with_index.map {|line, no| # 没有临时数组产生
sprintf("%d: %s\n", no, line)
}. \
first(10).each {|str| # 没有临时数组产生
puts(str)
}
} # 甚至在到达EOF之前都不读取数据

这样来避免产生多余的临时对象。这里谈到了惰性枚举,其实这个概念并不算太新鲜,在.NET引以为傲的Linq中,惰性枚举其实越来越重要。

初学C#的时候其实并不容易搞清楚所谓的IEnumerable和IEnumerator,有个时候就糊弄一下觉得大多数情况很少手工操作迭代器和枚举器,用一个foreach就巧妙的解决并自鸣得意。但是看了《CLR via C#》以及一些关于C#的案例和图书似乎都很少出现foreach,有时候还纳闷特么这些人是蠢的么...当然,后来发现foreach的实现方式导致其本身效率是不高的所以...。

回头看.NET的IEnumerable接口:

public interface IEnumerable
{
//
// Methods
//
[DispId (-4)]
IEnumerator GetEnumerator ();
}

这个接口只需要实现一个GetEnumerator的方法,非常简洁。

IEnumerator接口:

public interface IEnumerator
{
//
// Properties
//
object Current {
get;
} //
// Methods
//
bool MoveNext (); void Reset ();
}

于是我们便可以实现一个仅能duang出来一个的“列表”:

class OnlyOne : IEnumerable, IEnumerator
{
public IEnumerator GetEnumerator () => this;
public object Current => "caocaoda";
public bool MoveNext () => false;
public void Reset () {}
}

如果把false改为true那就可以一直艹艹哒啦。

但是这样的话,还是很麻烦,毕竟要我们手工实现,说好的C#简单呢...所以M$引入了一个迭代器,用以实现IEnumerable/IEnumerator。

class OnlyOne : IEnumerable
{
public IEnumerator GetEnumerator()
{
Int32 value = 0;
do {
yield return value++;
} while (false);
}
}

省事太多,通过DILASM可以看到其实编译器帮我们实现了前面我们自己写的方法。

通过IL不难看出,其实MoveNext()是一个Switch...

废话那么多回到惰性枚举上来,其实我们发现,IEnumerable和IEnumerator两个接口的实现其实是惰性的,也就是在需要的时候才会获取数据,而不会产生临时的数据,就像前面Ruby一样,使用迭代器不会产生额外的开销。如果我们把false改成了true,还没有“惰性”那玩意儿可够呛...

为什么说Linq其实很依赖惰性枚举呢...举个例子:

public static IEnumerable Take (Int32 much, IEnumerable s)
{
for (int i = 0; i < much; i++) {
yield return s [i];
}
}

我们就可以实现一个在数据源中抓much个元素的方法了。

你在说什么?##

其实我就是打算复习一下迭代器而已...

C#的惰性枚举的更多相关文章

  1. C#函数式程序设计之惰性列表工具——迭代器

    有效地处理数据时当今程序设计语言和框架的一个任务..NET拥有一个精心构建的集合类系统,它利用迭代器的功能实现对数据的顺序访问. 惰性枚举是一个迭代方法,其核心思想是只在需要的时候才去读取数据.这个思 ...

  2. swfupload多文件上传[附源码]

    swfupload多文件上传[附源码] 文件上传这东西说到底有时候很痛,原来的asp.net服务器控件提供了很简单的上传,但是有回传,还没有进度条提示.这次我们演示利用swfupload多文件上传,项 ...

  3. 聊一聊C# 8.0中的await foreach

    AsyncStreamsInCShaper8.0 很开心今天能与大家一起聊聊C# 8.0中的新特性-Async Streams,一般人通常看到这个词表情是这样. 简单说,其实就是C# 8.0中支持aw ...

  4. C# 8中的Async Streams

    关键要点 异步编程技术提供了一种提高程序响应能力的方法. Async/Await模式在C# 5中首次亮相,但只能返回单个标量值. C# 8添加了异步流(Async Streams),允许异步方法返回多 ...

  5. C#8.0中的 await foreach

    AsyncStreamsInCShaper 8.0 C# 8.0中支持异步返回枚举类型async Task<IEnumerable<T>> sync Streams这个功能已经 ...

  6. Python 入门基础11 --函数基础4 迭代器、生成器、枚举类型

    今日目录: 1.迭代器 2.可迭代对象 3.迭代器对象 4.for循环迭代器 5.生成器 6.枚举对象 一.迭代器: 循环反馈的容器(集合类型) 每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的 ...

  7. Stream01 定义、迭代、操作、惰性求值、创建流、并行流、收集器、stream运行机制

    1 Stream Stream 是 Java 8 提供的一系列对可迭代元素处理的优化方案,使用 Stream 可以大大减少代码量,提高代码的可读性并且使代码更易并行. 2 迭代 2.1 需求 随机创建 ...

  8. Effective Java - 构造器私有、枚举和单例

    目录 饿汉式单例 静态常量 静态代码块 懒汉式单例 尝试加锁 同步代码块 双重检查 静态内部类单例 枚举单例 Singleton 是指仅仅被实例化一次的类.Singleton代表了无状态的对象像是方法 ...

  9. Swift enum(枚举)使用范例

    //: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...

随机推荐

  1. [已解决]EnvironmentError: mysql_config not found

    $ pip install MySQL-python==1.2.5 报错: EnvironmentError: mysql_config not found 原因是缺少包 libmysqlclient ...

  2. weed-fs 压力测试

    阅读<Weed-FS/杂草文件系统 小文件存储集群 安装 使用 测试>中提到weedfs的负载压力不是很好,在看过代码后进行了相应测试,未发现负载压力有何问题.   weedfs mast ...

  3. Python list方法总结

    1. 向列表的尾部添加一个新的元素 append(...) L.append(object) -- append object to end 1 2 3 4 >>> a = ['sa ...

  4. 获取Spring容器中的Bean

    摘要 SpringMVC框架开发中可能会在Filter或Servlet中用到spring容器中注册的java bean 对象,获得容器中的java bean对象有如下方法 Spring中的Applic ...

  5. PHP的轻量消息队列php-resque使用说明

    日志未经声明,均为AlloVince原创.版权采用『 知识共享署名-非商业性使用 2.5 许可协议』进行许可. 消息队列处理后台任务带来的问题 项目中经常会有后台运行任务的需求,比如发送邮件时,因为要 ...

  6. php 万能加密

    function fue($hash,$times) { // Execute the encryption(s) as many times as the user wants for($i=$ti ...

  7. redis与memcached比较

    引用自:http://blog.csdn.net/e_wsq/article/details/23551799 最近需要用no-sql数据库来保存大量的数据,插入和查询都比较频繁,相对而言查询更加频繁 ...

  8. Ubuntu 针对 SSD 的优化方案

    . . . . . 首先看下 LZ 的分区情况: >$ sudo fdisk -l Disk /dev/sda: bytes heads, sectors/track, cylinders, t ...

  9. IE浏览器打开f12才正常

    IE浏览器打开f12才正常,最后发现是js中有向控制台打log的语句,程序执行到这些语句就不走了,去掉这些语句就好了!

  10. Android之ImageView 旋转

    方案一: (1)获取ImageView对应的图片,并将其转成Bitmap; (2)创建Matrix对象; (3)调用matrix.setRotate(     );设置旋转度数 (4)重新创建bitm ...