0

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

    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;
            }
    }

我想知道是否有更好的方法来解决这种模式。

4

1 回答 1

1

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

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

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

于 2020-12-18T09:09:30.463 回答