如何将值传递给迭代器

How to Pass Value to Iterator

提问人:Bondolin 提问时间:11/8/2023 最后编辑:VLAZBondolin 更新时间:11/9/2023 访问量:75

问:

在 JavaScript 中,我们有运算符,它能够返回一个值,该值可以选择性地通过该方法提供给生成器。从下一个yieldnext()

参数

value可选
要发送到生成器的值。

该值将作为表达式的结果进行赋值。例如,在 中,传递给函数的值将分配给 。yieldvariable = yield expression.next()variable

产生

返回值

返回传递给生成器方法的可选值以继续其执行。next()

在 C# 中,我理解粗略的等效项是 IEnumerator.MoveNext()。但是,虽然采用可选参数,但 中似乎没有任何等效参数。Generator.prototype.next()next()valueMoveNext()

我真的很想要某种能够将值传递给 C# 迭代器的方法,就像我可以将值传递给 JavaScript 生成器一样。我想我也许可以尝试使用通道等,但我希望利用 C# 自己的运算符提供的语法糖。有谁知道这是否可行?yield

C# 迭代器 生成器 协程

评论

1赞 Jonathan Dodds 11/8/2023
C# 迭代器不是生成器。IEnumerator.MoveNext() 不接受参数。您将无法更改呼叫中的顺序,如果这是您尝试执行的操作。您可以创建一个返回 .MoveNext()IEnumerable<T>
0赞 Bondolin 11/8/2023
你是对的,相似但不相同。我试图看看是否有任何解决方法来解决不带任何参数的事实。也许没有,我只需要接受这样一个事实,即我想要的 C# 语法目前不存在。在这种情况下,我想知道有什么选择。也许我只需要熟悉频道......MoveNext
0赞 Bondolin 11/8/2023
也许我应该把它包含在问题中,但如果你想了解更多我想要做的事情的背景信息,你可以在这里查看 redux-saga 的“示例用法”: redux-saga.js.org
0赞 Jonathan Dodds 11/9/2023
我在示例中没有看到调用,但我认为重要的部分是用户 ID API 调用的“副作用”。next(arg)
0赞 Bondolin 11/9/2023
@JonathanDodds没错,这发生在 redux-saga 中间件库中。示例中的 saga 生成器函数对 redux-saga 产生了影响,redux-saga 执行调用并用于将响应传递回生成器。yieldcallnext(result)

答:

-1赞 Bondolin 11/9/2023 #1

好的,在摆弄了一些之后,这里有一个粗略的答案开始。它松散地基于这个例子

namespace Coroutine
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    internal class Program
    {
        static void Main(string[] args)
        {
            var point = new Point(1, 2, 3);
            foreach (var coordinate in point)
            {
                Console.Write(coordinate);
                Console.Write(" ");

                point.Arg = coordinate;
            }
            // Output: 1 3 6
        }

        public class Point
        {
            public Point(int X, int Y, int Z)
            {
                this.X = X;
                this.Y = Y;
                this.Z = Z;
                this.Arg = 0;
            }

            public int X { get; }
            public int Y { get; }
            public int Z { get; }
            public object Arg { get; set; }

            public IEnumerator<int> GetEnumerator()
            {
                yield return X + (int)Arg;
                yield return Y + (int)Arg;
                yield return Z + (int)Arg;
            }
        }
    }
}

有点丑,但我想经过一些清理后,这可能会起作用。

基本上代替了通话,我在通话前设置。代替 ,我有 .move(value)ArgforeachMoveNext()variable = yield expression;yield expression; variable = Arg;

测试的重点是验证我是否可以将数据从外部调用者传递到迭代器中,例如修改迭代器的行为。这种方法仍然在一定程度上使用了语法,即不手动重新创建编译器生成的迭代器状态机。foreach/yield

希望这对任何有相同问题的人有用,并很高兴听到您可能有的任何其他想法。我想我会在实际生产使用它之前清理它,也许添加一些实用方法和模板类型,但现在这是一个简单的测试,它的主要思想。