yield关键字是微软的一个语法糖,使用它可以让我们的代码具有更高可读性和更好性能。有了yield关键字,当我们需要返回IEnumerable类型的时候,直接yield返回数据就可以了。也不用new一个list,或其他类型。 :::info 如果要通过计算并返回一个集合数据,传统的办法就是建一个IEnumerable集合,然后把计算出来的数据装到这个集合里面再返回。如果这个计算很慢,一秒钟算出一个值,10个值算出来再返回展示给用户,相当于有10秒钟,用户不知道程序在干嘛。而用yield return,每秒钟就能给用户提供一个值。虽然全部完成也要10秒钟,但是体验感不同。 :::

yield语法

  1. yield return <expression>;
  2. yield break;
  1. yield return语句返回集合的一个元素,并移动到下一个元素上
  2. yield break可以停止迭代,相当于正常代码块的 return 语句(迭代器中直接使用 return 是非法的)
  3. 包含yield语句的方法或属性是迭代器。迭代器必须满足以下要求:
    1. 返回类型必须是IEnumerable、IEnumerable、IEnumerator或 IEnumerator
    2. 它不能有任何ref或out参数
  4. yield return语句不能位于try-catch块。
  5. yield return语句可以位于try-finally的try块。
  6. yield break语句可以位于try块或catch块,但是不能位于finally块。

    例子

    1. static void Main(string[] args)
    2. {
    3. //可用一个变量来装,也可以直接迭代
    4. foreach (var item in yield1(100))
    5. {
    6. Console.WriteLine(item);
    7. }
    8. Console.ReadLine();
    9. }
    10. //用法1:每个0.5秒打印返回一个元素
    11. static IEnumerable<int> yield1(int n)
    12. {
    13. for(int i = 1; i < n; i++)
    14. {
    15. if (i % 88 == 0)
    16. {
    17. yield break;
    18. }
    19. if (i % 2 == 0)
    20. {
    21. Thread.Sleep(500);
    22. yield return i;
    23. }
    24. }
    25. }
    26. //用法2:打印123的时候每隔一秒打印一次
    27. static IEnumerable<int> yield2()
    28. {
    29. Thread.Sleep(1000);
    30. yield return 1;
    31. Thread.Sleep(1000);
    32. yield return 22;
    33. Thread.Sleep(1000);
    34. yield return 333;
    35. yield return 4444;
    36. yield return 55555;
    37. yield return 666666;
    38. }

    关于yield的性能比较

    1. static void Main(string[] args)
    2. {
    3. DateTime t1 =DateTime.Now;
    4. foreach (var item in listYieldReturn())
    5. {
    6. //Console.WriteLine(item);
    7. }
    8. DateTime t2 = DateTime.Now;
    9. Console.WriteLine("耗时:"+(t2-t1).TotalMilliseconds);
    10. }
    11. //耗时1450ms,进程占用内存12MB
    12. static IEnumerable<string> listYieldReturn()
    13. {
    14. for (int i = 0; i < 100000000; i++)
    15. {
    16. yield return "这是一段字符串";
    17. }
    18. }
    19. //耗时3250ms,进程占用内存2.1GB
    20. //需要把Main方法里面的东西封装到一个返回void的方法里面。Main里面调用这个方法。之后再GC.Collect(GC.MaxGeneration);才能回收掉这2G的垃圾
    21. static IEnumerable<string> listReturn()
    22. {
    23. List<string> list = new List<string>();
    24. for(int i = 0; i < 100000000; i++)
    25. {
    26. list.Add("这是一段字符串");
    27. }
    28. return list;
    29. }