【发布时间】:2021-05-01 04:18:45
【问题描述】:
我有如下界面:
public interface IValidationSystem<T>
{
IAsyncEnumerable<ValidationResult> ValidateAsync(T obj);
}
我正在尝试以这种方式实现它:
public class Foo
{ }
public class Bar
{ }
public class BarValidationSystem : IValidationSystem<T>
{
public async IAsyncEnumerable<ValidationResult> ValidateAsync(Bar bar)
{
var foo = await GetRequiredThingAsync();
return GetErrors(bar, foo).Select(e => new ValidationResult(e)).ToAsyncEnumerable();
}
private static IEnumerable<string> GetErrors(Bar bar, Foo foo)
{
yield return "Something is wrong";
yield return "Oops something else is wrong";
yield return "And eventually, this thing is wrong too";
}
private Task<Foo> GetRequiredThingAsync()
{
return Task.FromResult(new Foo());
}
}
但这不能编译:
CS1622 无法从迭代器返回值。使用 yield return 语句返回一个值,或者使用 yield break 结束迭代。
我知道我可以通过迭代枚举来修复:
foreach (var error in GetErrors(bar, foo))
{
yield return new ValidationResult(error);
}
或者通过返回 Task<IEnumerable<ValidationResult>>:
public async Task<IEnumerable<ValidationResult>> ValidateAsync(Bar bar)
{
var foo = await GetRequiredThingAsync;
return GetErrors(bar, foo).Select(e => new ValidationResult(e));
}
但我想了解为什么我不能返回 IAsyncEnumerable。在编写“经典”IEnumerable 方法时,您可以返回 IEnumerable 或 yield 返回多个值。为什么我不能对 IAsyncEnumerable 做同样的事情?
【问题讨论】:
-
我试图查看这个,但是缺少太多东西来编译这个。你能提供一个minimal reproducible example(最好有小提琴链接)吗?
-
@fharreau:不,fiddle 仍然错过了
ToAsyncEnumerable()的定义。抱歉,我出去了……编译的工作量太大(需要重新开始工作)。 -
在阅读spec proposal 时,这看起来像是一个错误,或者至少是一个无意的限制。其意图显然是通过使用
yield来指示异步迭代器,就像同步迭代器一样;然而,async和返回类型的组合似乎将其锁定为迭代器。 -
@Jeroen:这就是我对情况的理解。谢谢你把它写成一个清晰的句子!
标签: c# iasyncenumerable