正在为访问者 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
,也可以通过值元组返回所有内容)
考虑这个片段(比原始代码简单得多):
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
,也可以通过值元组返回所有内容)