【问题标题】:yield in C# by infinite loop example通过无限循环示例在 C# 中产生
【发布时间】:2014-03-17 08:47:23
【问题描述】:

我试图了解 yield 在 C# 中的工作原理。为了测试,我做了一些示例代码:

using System;
using System.Text;

namespace ConsoleApplication1
{
    class GameFrame
    {
    };

    class GameState
    {
        public static GameFrame Begin()
        {
            Console.WriteLine("GameState.Begin");

            return new GameFrame();
        }

        public static GameFrame Play()
        {
            Console.WriteLine("GameState.Play");

            return new GameFrame();
        }

        public static System.Collections.Generic.IEnumerator<GameFrame> MainLoop()
        {
            yield return Begin();

            while (true)
            {
                yield return Play();
            }
        }
    };


    class Program
    {
        static void Main()
        {
            while (GameState.MainLoop() != null)
            {
            }
        }
    }
}

此代码仅尝试运行一次 Begin 函数并调用无限次函数 Play。请告诉我为什么我从来没有在控制台中看到我的消息?

【问题讨论】:

    标签: c# loops state yield


    【解决方案1】:

    你需要枚举集合,你只检查结果是否为null,不会开始枚举。

    foreach (var frame in GameState.MainLoop())
    {
        //Do whatever with frame
    }
    

    要使其与`foreach 一起使用,您可以使MainLoop 方法返回IEnumerable&lt;GameFrame&gt; 而不是IEnumerator&lt;GameFrame&gt; 或者只使用

    var enumerator = GameState.MainLoop();
    while (enumerator.MoveNext())
    {
         //Do whatever with enumerator.Current
    }
    

    【讨论】:

    • 您是否尝试自己编译它。它不能用 foreach 编译。因为它不返回 IEnumerable 并且不实现它。它会用while编译,但它仍然是INFINITE。因为 WHILE LOOP 永不停止
    • @Selman22 更新了我的答案。顺便说一句,INFINITE 循环有什么问题?如果这就是内涵,那有什么问题?
    • @SriramSakthivel 你读过这个问题吗? 此代码仅尝试运行一次 Begin 函数并调用无限次函数 Play。 如果这是我的意图,我很确定问题会有所不同!
    • @Selman22 我已经阅读了这个问题。您应该仔细阅读问题。 OP 声明他的代码试图调用一次Begin 和无限次调用Play,这不起作用并现在解决了。得到它?如果不看MainLoop方法,一切都会变得清晰
    • 这不是我的错。我从这句话中了解到,OP 有一个无限循环,他问为什么?如果他想创建一个无限循环并且他无法获得它,那么他应该说为什么我不能获得一个无限循环?这段代码应该这样做这个 但它没有。 明白了吗?
    【解决方案2】:

    那是因为你得到了一个 IEnumerable&lt;GameFrame&gt;,但实际上从未遍历它。

    试试这个:

    var frames = GameState.MainLoop();
    foreach(var frame in frames)
    {
        // use the frame
        // e.g. frame.Show(); (note: in your example code, 
        // GameFrame doesn't have any members)
    }
    

    【讨论】:

    • +1 讨厌的人会讨厌,没关系。好答案..我也被否决了:(
    • 这仍然是一个无限循环。并且该代码无法使用 foreach 编译。在编写答案之前,您应该尝试自己编译
    • @Edward83 因为它是错误
    【解决方案3】:

    GameState.MainLoop() 返回 IEnumerable,它表示您可以从中获取项目的无限集合。当您使用 yield 时,元素仅在需要时才被评估,因此只有当您“触摸”和 item 时,您才会看到一些输出

     GameState.MainLoop().Take(5).ToList();
    

    我不建议将 foreach 与无限循环一起使用。

    【讨论】:

    • 虽然我不推荐 foreach (是的,我知道这是一个例子)(我将其作为第三个回复)
    • 在我的示例中不是 IEnumerable 返回,而是 IEnumerator。不过谢谢你的回答。
    • 哎呀抱歉,这一定是因为我的 linq 成瘾,我到处都看到 ienumerable ;)
    猜你喜欢
    • 2011-06-26
    • 2011-08-23
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多