对于”yield”这个关键字我已经见过N次了,直到最近我才知道这个关键字所蕴含的力量。我将在下面展示出一些使用”yield”让你的代码有更高可读性和更好性能的例子.

为了让你对yield有一些快速概览,我首先要展示一个没有使用这个关键字的例子,下面的代码很简单,但在我最近的项目中却很常见

IList<string> FindBobs(IEnumerable<string> names)
{
var bobs = new List<string>(); foreach(var currName in names)
{
if(currName == "Bob")
bobs.Add(currName);
} return bobs;
}

注意在这里我使用IEnumerable<string>作为参数类型并以IList<string>作为返回类型,通常来说,我更倾向于在参数输入的类型方面的范围越宽越好,但在返回类型上面更加严格(译者按:即输入时多用基类或接口,返回时用子类或实现类),对于输入来说,如果你需要用foreach来对其进行循环的话,使用IEnumerable会更有意义。而对于输出(译者按:也就是返回),我使用接口来让实现部分可以改变。在这里我想让调用者省去生成列表的麻烦,所以我选择list作为返回类型.

而问题在于,我的设计并不具有可链接性,这样的设计需要产生列表作为返回值,实现上,这个列表或许不会很大,但这并不必要

现在,让我们来看看以“yield”的方式来做这些,而后我会解释如何使用它,以及它工作的原理。

IEnumerable<string> FindBobs(IEnumerable<string> names)
{
foreach(var currName in names)
{
if(currName == "Bob")
yield return currName;
}
}

在这个版本中,我们将返回类型改为IEnumerable,并且我们使用”yield return”.注意我再也不需要创建一个列表,现在是不是有些迷惑的?别着急,在理解它的工作方式的情况它会变的越来越简单.

当使用”yield return”关键词组时,.net会为你生成一大串管道代码,你可以尽管假装这是个魔法。当开始在被调用的代码中循环时(这里不是list),实现上发生的是这个函数被一遍一遍的调用,但每一次都从上一次执行退出的部分开始继续执行.

传统的执行方法

  1. 调用函数
  2. 函数执行并返回list
  3. 调用部分使用返回的list

Yield的执行方法

  1. 调用函数
  2. 调用者请求item
  3. 下一个item返回
  4. 回到步骤2

虽然yield执行的实现貌似有些复杂,但我们最终只需要一次“弹出”一个item,而不是创建整个list并返回.

对于句法说,我个人认为yield更加简洁,并且对于传递函数的用途表现的更好(译者按:也就是代码可读性),我使用IEnumerable作为返回类型来通知调用者它可以被foreach循环并且返回数据,而调用者现在可以自己决定它是否愿意将返回值存放到列表中,即使这会以性能作为代价。

在我提供的这个简单例子中,也许你并不能发现很多使用yield的好处,然而,你可以在调用者需要取消遍历所有的函数提供的内容时节省很多不必要的工作,当你在方法链接时使用yield,你可以省下的工作(时间)或许会成倍叠加。

Ayende已经有了很棒的例子:using yield for a slick pipes & filters implementation,他甚至还讲述了:version that is multi-threaded。这让我觉得非常有趣.

最开始我对yield的保留意见是使用这个关键字或许会导致潜在的性能问题,但实际上,至今为止我还未能发现任何信息来说明关于yield对性能的影响,而我在上面提到提高性能的地方远远大于编译器overhead那部分。

小结

Yield可以让你的代码更加高效并拥有更高的可读性,已经是.net 2.0时代了,我想已经没有什么借口可以阻止我们学习和使用yield.

---------------------------------------------------------------------

译者:这篇文章是我翻译的十个鲜为人知的C#关键字里的pangxiaoliang[北京]流浪者同学在评论中提出的意见,那篇文章只是做了个总结,我发现已经有关于论述更深层次的好文了,所以我就不重复发明轮子直接进行翻译了,在翻译的过程中我也学到了不少.谢谢

原文链接:http://www.ytechie.com/2009/02/using-c-yield-for-readability-and-performance.html

使用C# yield关键字来提高性能和可读性的更多相关文章

  1. 使用yield关键字来提高性能

    比如我们在开发当中往往会遇到这样的问题: public List<string> FindBobs(string [] names)   { List<string> bobs ...

  2. C# 中的迭代器 yield关键字 提高性能和可读性

    展示一个例子 IList<string> FindBobs(IEnumerable<string> names) { var bobs = new List<string ...

  3. 从range和xrange的性能对比到yield关键字(中)

    上节提出了range和xrange的效率问题,这节我们来探究其中的原因   yield的使用   我们看下面的程序: #coding: utf-8 def test(): print 4 print ...

  4. CSS性能分析,如何优化CSS提高性能

    不负十年后的自己,共勉! 前端性能优化一直是一个比较热门的话题,我们总是在尽我们最大的努力去,提高我们的页面性能,比如减少HTTP请求,利用工具对资源进行合并压缩,脚本置底,避免重复请求,css sp ...

  5. 从yield关键字看IEnumerable和Collection的区别

    C#的yield关键字由来以久,如果我没有记错的话,应该是在C# 2.0中被引入的.相信大家此关键字的用法已经了然于胸,很多人也了解yield背后的“延迟赋值”机制.但是即使你知道这个机制,你也很容易 ...

  6. C#的yield关键字

    using System; using System.Collections.Generic; using System.Reflection; using System.Text.RegularEx ...

  7. C#中yield关键字理解

    yield关键字之前用得较少,但是在做项目开发的过程中也遇到了,当时有点迷惑,就顺便研究学习了一下,以下是个人理解,不到之处欢迎拍砖!废话就到这,上代码: class Program { static ...

  8. 使用SQL Server 2000索引视图提高性能

    什么是索引视图? 许多年来,Microsoft? SQL Server? 一直都提供创建虚拟表(称为视图)的功能.在过去,这些视图主要有两种用途: 提供安全机制,将用户限制在一个或多个基表中的数据的某 ...

  9. Java编程 “提高性能” 应尽力做到

    除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源总结的一些在Java编程中尽可能要做到的 ...

随机推荐

  1. ZK 代码自动提示

    1.设置xsd 打开eclipse,Window-Preference,进行如下设置: 2.创建zul文件 (1)打开File—New—Other窗口,新建XML File文件: (2)选择新建文件所 ...

  2. uilmit 优化

    #!/bin/bash sed -i "/^ulimit -SHn.*/d" /etc/rc.local echo "ulimit -SHn 102400" & ...

  3. Eclipse序列号生成代码

    import java.io.*; public class MyEclipseGen { private static final String LL = "Decompiling thi ...

  4. win10如何让她闭嘴、按什麽建系统都要说话、如何让她闭嘴?

    win10如何让她闭嘴.按什麽建系统都要说话.如何让她闭嘴? 开始 设置 轻松使用 讲述人,关掉……

  5. IOS第一天多线程-04GCD通信

    **** #define HMGlobalQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) #define HMM ...

  6. 【iCore3 双核心板】例程十五:USB_CDC实验——高速数据传输

    实验指导书及代码包下载: http://pan.baidu.com/s/1gemYjz9 iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  7. ModelAndView学习整理

    ModelAndView mav = new ModelAndView("/media/play-video");是什么意思 1.这是SpringMVC里面的问题啊!2.这叫返回一 ...

  8. [daily][device] linux添加打印机

    只用过HP的打印机,用过两个,分别是:HP_p2055dn, 和 HP_LaserJet_Professional_M1216nfh  别的不知道.以下内容仅试用于HP打印机. 第一:装HP,打印机工 ...

  9. iOS 横竖屏切换(应对特殊需求)

    iOS 中横竖屏切换的功能,在开发iOS app中总能遇到.以前看过几次,感觉简单,但是没有敲过代码实现,最近又碰到了,demo尝试了几种情况,这里就做下总结.注意 横屏两种情况是反的你知道吗? UI ...

  10. Decimal To Fraction 小数转换成分数

    以0.25为例, 0.25 * 100 = 25, 求25 和 100 的最大公约数gcd. 25/gcd 为分子. 100/gcd为分母. //小数转分数 //0.3 -> 3/10, 0.2 ...