例子:在不使用yieId时,通常我们都会采取先遍历再把元素加到新的List中

            using (var reader = SqlHelper.ExecuteReader(""))
{
if (reader.HasRows)
{
IList<Captcha> list = new List<Captcha>();
while (reader.Read())
{
list.Add(SqlHelper.MapEntity<Captcha>(reader));
}
return list;
}
}
return null;

接下来我们用它(yieId)来改善以上代码:

using (var reader = SqlHelper.ExecuteReader(""))
{
if (reader.HasRows)
{ while (reader.Read())
{
yield return SqlHelper.MapEntity<Captcha>(reader);
} }
}

这里需要注意的是在使用yieId时,返回值类型必须为IEnumerable

现在我们简单介绍下yieId,先分享一个错误的理解,注意 是错误的理解

根据上图,我们定义一个变量作用域然后开辟一个List变量,在代码执行的过程中都通过这个List来Add这个元素。最后返回这个新的List。这可以当成我们对yieId的初步理解,但yieId绝对不是那么简单的。

我们来写一个简单的Demo,让您更快的理解yieId。

如题:定义一个string数组,然后将这个数组转换成Int数组

string[] strs = new string[] { "", "", "" };

比较普遍的处理方式就是遍历这些元素添加到一个新的数组里,至于代码怎么实现这里就不讲了。今天的重点是如何通过yieId来更高效的实现这个效果

首先我们来定一个一个静态类并且返回值类型为IEnumerable的方法:

static IEnumerable<int> GetInts(string[] strs)
{ foreach (var item in strs)
{
yield return Convert.ToInt32(item);
}
}

当然,这里用linq来实现将回更简洁,不过这不是咱们今天的话题,就不聊它了。

以上代码就如上图所说,先开辟一个临时空间,再通过yieId return把数据丢到这个临时空间中。最后把临时空间的数据全部放进去

string[] strs = new string[] { "", "", "" };
int[] ints = GetInts(strs).ToArray();
foreach (var item in ints)
{
Console.WriteLine(item.GetType());
}
Console.ReadKey();

为了让大伙能看的更明白,我这边使用GetType(),以便有效的让您知道读出来的数据类型是否准确

这样,移掉GetType()就能直接得到1,2,3 的结果了


到这边,我想您应该对yieId有一个自己的初步理解了吧?接下来我们来分析下yieId带给我们的好处。

1.代码更精简 (这个刚才您应该有体会到了)

除此之外还有一个特点,我们来改动之前的这一段代码:

static void Main(string[] args)
{
string[] strs = new string[] { "", "", "" };
int[] ints = GetInts(strs).ToArray();
foreach (var item in ints)
{
Console.WriteLine(item.GetType());
}
Console.ReadKey();
}
static IEnumerable<int> GetInts(string[] strs)
{ foreach (var item in strs)
{
Console.WriteLine(item.GetType());//改动1
yield return Convert.ToInt32(item);
}
}

请思考这个执行出来的结果会是怎么样的呢?(先自动屏蔽下图哦)

这个结果还是合情合理的,在调用GetInts()时,数组的类型还是String,并且调用3次。再执行遍历,转换成Int类型,结果刚好是3个string 3个int。

那为什么会是3个string 3个int了,原因是因为我们调用了.ToArray()这个方法,我们尝试把这个方法去掉。但这时我们需要改变被转换的变量的返回值类型

 IEnumerable<int> ints = GetInts(strs);

执行结果:

对于这个执行结果,就开始有点好奇了。怎么会是这样呢?我们来研究下yieId到底发挥了什么效果。

根据上图,在调试的过程中我们发现,在执行F11(逐语句)时,并不会跑到GetInts()这个方法体中来。那就说白了,当我们在使用yieId return的时候,它并没有真正的被执行。

当我们执行foreach遍历的时候,这个ints的变量事先会去调用GetEnumerator()这个方法来拿到这个迭代器,然后通过这个迭代器去迭代的时候,就像去读这个数组的时候遍历最后才调用这个GetInts(),

就像一个指针去搜寻每一个元素一样。另外,在调试中,当yieId return后,yieId会将这个方法体进行冻结。当需要继续执行的时,会根据遍历的次数来继续执行。这时指针会继续往下移动一位。

这时,我们回到之前用List去实现这样的效果,从代码执行上来看。就会浪费了很多不需要的循环。在使用yieId后,我们可以有效的去处理这个代码执行效率的问题,我们在遍历这个ints时,加一层判断

 if (item > )
break;

这样当不满足条件时,就不会去使用它(GetInts())这个方法,相当于它自动被冻结住了。我们看一下执行结果:

这就是yieId的好处,能很好的提高代码执行效率。有很多人几乎都没接触甚至根本不知道这个东西的存在,其实个人认为只是因为我们所见到的市场代码质量不是很高。其实只要你去看一些比较著名的开源项目,比如EF,那里面都会大量使用到这个yieId关键词,包括MVC的源码里也很多。

yieId浅谈的更多相关文章

  1. 浅谈 Fragment 生命周期

    版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...

  2. 浅谈 LayoutInflater

    浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...

  3. 浅谈Java的throw与throws

    转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...

  4. 浅谈SQL注入风险 - 一个Login拿下Server

    前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...

  5. 浅谈WebService的版本兼容性设计

    在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...

  6. 浅谈angular2+ionic2

    浅谈angular2+ionic2   前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别.   1. 项目所用:angular2+ionic2 ...

  7. iOS开发之浅谈MVVM的架构设计与团队协作

    今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...

  8. Linux特殊符号浅谈

    Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...

  9. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

随机推荐

  1. (转载)C++创建对象的两种方法

    (转载)http://blog.sina.com.cn/s/blog_586b6c050100dhjg.html 在C++里,有两种方法创建对象: 方法一: ClassName object(para ...

  2. HDU-2548 两军交锋

    两军交锋 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  3. Enter键提交表单

    input type="submit"在360浏览器上不能提交   用了这个 <input type="button" class="btn b ...

  4. Ubuntu----1

    1. 安装ubuntu之后,你必须要做的事情, 引自:http://itsfoss.com/things-to-do-after-installing-ubuntu-13-04/ 但是对于国人来讲,墙 ...

  5. Bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 dijkstra,堆,分层图

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1573  Solv ...

  6. C语言中的宏

    写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_ ...

  7. HDU 4737 A Bit Fun 2013成都 网络赛 1010

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4737 题目大意:给定一系列数,F(i,j)表示对从ai到aj连续求或运算,(i<=j)求F(i, ...

  8. 在CentOS搭建Git服务器 转

    在CentOS搭建Git服务器 来自 :http://www.jianshu.com/p/69ea5ded3ede 前言 我们可以GitHub发布一些开源代码的公共仓库,但对于私密仓库就需要收费了.公 ...

  9. PAT 1012. The Best Rank

    To evaluate the performance of our first year CS majored students, we consider their grades of three ...

  10. 站在巨人的肩膀上学习Android开发

    我们知道,一開始最好的学习方法是模仿,尤其是模仿巨人. 那说到Android开发的模仿自然就是分析并研究主流程序的布局.实现方法.进而提升自己的技术. 第一招----逆向project 要分析&quo ...