正在为访问者 IAsyncEnumerable 寻找更好的模式?

Looking for a better pattern for a visitor-IAsyncEnumerable?

考虑这个片段(比原始代码简单得多):

    async IAsyncEnumerable<(DateTime, double)> GetSamplesAsync()
    {
       // ...

            var cbpool = new CallbackPool(
                HandleBool: (dt, b) => { },
                HandleDouble: (dt, d) =>
                {
                    yield return (dt, d);     //not allowed
                });

            while (await cursor.MoveNextAsync(token))
            {
                this.Parse(cursor.Current, cbpool);
            }
    }

    private record CallbackPool(
        Action<DateTime, bool> HandleBool,
        Action<DateTime, double> HandleDouble
        );

那么,下面的Parse只是原始行为的等价物。

    Random _rnd = new Random();
    void Parse(object cursor, CallbackPool cbpool)
    {
        double d = this._rnd.NextDouble();  //d = [0..1)
        if (d >= 0.5)
        {
            cbpool.HandleDouble(new DateTime(), d);
        }
        else if (d >= 0.25)
        {
            cbpool.HandleBool(new DateTime(), d >= 0.4);
        }
    }

但是,我确实喜欢 GetSamplesAsync 代码,但编译器不喜欢:yield 不能在 lambda 中使用。

因此,我按如下方式更改了函数,尽管它的可读性大大降低(而且也容易出错):

    async IAsyncEnumerable<(DateTime, double)> GetSamplesAsync()
    {
       // ...

            (DateTime, double) pair = default;
            bool flag = false;
            var cbpool = new CallbackPool(
                HandleBool: (dt, b) => { },
                HandleDouble: (dt, d) =>
                {
                    pair = (dt, d);
                    flag = true;
                });

            while (await cursor.MoveNextAsync(token))
            {
                this.Parse(cursor.Current, cbpool);
                if (flag)
                {
                    yield return pair;
                }
                flag = false;
            }
    }

不知道有没有更好的办法解决这种模式

外部 flag/pair 非常危险且不必要(它会强制关闭); bool 似乎可以从 Parse 方法 返回 ,例如:

await foreach (var item in cursor)
{
    if (Parse(item, cbpool, out var result))
        yield return result;
}

(如果您不喜欢 out,也可以通过值元组返回所有内容)