zoukankan      html  css  js  c++  java
  • yieId浅谈


    例子:在不使用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[] { "1", "2", "3" };

    比较普遍的处理方式就是遍历这些元素添加到一个新的数组里,至于代码怎么实现这里就不讲了。今天的重点是如何通过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[] { "1", "2", "3" };
                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[] { "1", "2", "3" };
                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 > 1)
        break;

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

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

  • 相关阅读:
    Bzoj 1036: [ZJOI2008]树的统计Count
    cogs 1176. [郑州101中学] 月考
    cogs 610. 数对的个数
    Codevs 1247 排排站
    洛谷P1962 斐波那契数列
    Codevs 1051 接龙游戏
    2012 Noip提高组 Day2
    2012 Noip提高组 Day1
    poj1061 青蛙的约会
    一些常用的模板
  • 原文地址:https://www.cnblogs.com/byvar/p/4393820.html
Copyright © 2011-2022 走看看