【问题标题】:What's the use of yield break? [duplicate]收益中断有什么用? [复制]
【发布时间】:2010-10-04 14:38:06
【问题描述】:

可能重复:
What does “yield break;” do in C#?

任何人都可以看到使用“break”或“return”无法实现的“yield break”语句的用途。

这句话似乎完全没用。更重要的是,如果没有这个语句,“yield return X”语句可以被简化为“yield X”,这样更易​​读。

我错过了什么?

【问题讨论】:

    标签: c# yield iterator


    【解决方案1】:

    yield break 指定方法应该停止返回结果。 “返回”本身不够好,甚至可能导致错误,因为方法的返回类型必须是 IEnumerable。

    我不确定为什么还需要 return 关键字。我最好的猜测是它有助于使声明的意图更加清晰。

    如果你有兴趣,这篇文章解释了 yield 在幕后做了什么

    Behind the scenes of the C# yield keyword

    【讨论】:

    • 这不是我阅读行为的方式——“yield break”取消了整个方法,什么也不返回。您可以有 'yield return(ed)' 10K 项目,但如果在同一方法中点击“yield break”,则总共获得 0 个项目。
    • @Dave:我不这么认为......那么惰性求值如何在迭代器块中工作?
    • @Dave,不,yield break 停止返回任何更多项目,但不会(也不能)取消已经返回的项目。
    • @Bob: "return" 本身不会导致错误 - 它根本不会在迭代器块内编译。 'yield return' 关键字组合对于防止破坏现有代码是必要的。
    • @configurator,Miles 询问为什么不能单独使用 return,如果允许,语法可能会令人困惑,从而导致错误。
    【解决方案2】:

    您需要区分返回一个已经存在的 IEnumerable 实现(也许您要返回一个 List)和一个匿名迭代器。

    您不能只使用 return 或 break,因为它们是可用于其他目的的有效关键字。你也不能单独使用yield,因为你需要有一种方法来指定你是在枚举中返回一个项目,还是结束枚举,因此需要yield return和yield break。

    【讨论】:

      【解决方案3】:

      在迭代器块中使用return 语句是非法的。此外,如果允许break 语句在迭代器块中影响迭代,它可以用于双重目的:它可以用于跳出循环或跳出开关,也可以用于中断在整个迭代中。

      yield returnyield break 本身就是两个关键字,它们似乎都是必要的。

      【讨论】:

        【解决方案4】:

        return 语句用于从函数返回值。

        如果你有这样的迭代器函数:

        public IEnumerable<int> IteratorOverInt() { }
        

        上述函数中的 return 语句需要返回一个填充的 IEnumerable&lt;int&gt;

        public IEnumerable<int> IteratorOverInt() {
            return new List<int> { 1, 2, 3, 4 };
        }
        

        但如果您正在处理迭代器函数,您将使用yield return,因此您的代码可能如下所示:

        public IEnumerable<int> IteratorOverInt() {
            for (int i = 0; i < 4; i++) {
                yield return i;
            }
        }
        

        所以yield return 返回一个int,而方法签名要求IEnumerable&lt;int&gt;

        在上述情况下,return 语句会做什么?返回结果覆盖收益率?将任何内容连接到收益率? return 在上述情况下没有多大意义。

        因此我们需要一种在迭代器块中有意义的return 方法,这就是yield break 的原因。

        当然,您可以使用break 来执行此操作,但是如果您有更多要执行的代码,您将如何退出函数体?将所有内容包装在一个复杂的 if-else 块中?我会说只有yield break 会更好。

        【讨论】:

          【解决方案5】:

          举个代码示例,假设你想编写一个迭代器,如果源为 null 或为空,则不返回任何内容。

          public IEnumerable<T> EnumerateThroughNull<T>(IEnumerable<T> source)
          {
              if (source == null)
                  yield break;
          
              foreach (T item in source)
                  yield return item;
          }
          

          没有yield break,就不可能在迭代器中返回一个空集。

          【讨论】:

          • @Cameron:感谢这个代码示例,它帮助我解决了我遇到的问题!赞一个!
          • yield break 返回一个空的可枚举...基本上(在您的情况下)与return new T[0] 相同,但不创建空数组。
          • 好吧,我们可以让 if 语句只在 source!=null 时运行,但要注意
          【解决方案6】:

          yield break 和 break 做完全不同的事情!看看

          for(int i = 0; i < 10; ++i) {
             if(i > 5) { break; }
             yield return i;
          }
          
          for(int v = 2710; v < 2714; v+=2) {
             yield return v;
          }
          
          for(int s = 16; s < 147; ++s) {
             if(s == 27) { yield break; }
             else if(s > 17) { yield return s; }
          }
          

          输出将是以下值的 IEnumerable:0、1、2、3、4、5、2710、2712、18、19、20、21、22、23、24、25、26

          这里有一些没有用的方法,但它说明了你可以将 yield break 和 break 组合到同一个方法中,它们做了两件不同的事情! Break 只是跳出循环,yield break 完全结束方法。

          我猜未使用 return 的原因是因为您没有在方法中自己返回 IEnumerable。此外,对于这种迭代情况,您不认为 yield break 比 return 更清晰吗?我个人做的。

          【讨论】:

          • 大声笑哦,我不是故意的,我会解决的。
          猜你喜欢
          • 2019-09-19
          • 2016-12-14
          • 2019-03-22
          • 2013-05-31
          • 2011-02-24
          • 2010-09-06
          • 1970-01-01
          • 2017-05-30
          相关资源
          最近更新 更多