是否有一种方便的方法可以使用异步函数作为可观察对象的Where
运算符的谓词?
例如,如果我有一个很好的整洁但可能长时间运行的函数定义如下:
Task<int> Rank(object item);
是否有将其传递给Where
并保持异步执行的技巧?如:
myObservable.Where(async item => (await Rank(item)) > 5)
过去,当我需要这样做时,我已经使用SelectMany
并将这些结果与原始值一起投影到新类型中,然后根据它进行过滤。 / p>
myObservable.SelectMany(async item => new
{
ShouldInclude = (await Rank(item)) > 5,
Item = item
})
.Where(o => o.ShouldInclude)
.Select(o => o.Item);
我认为这是非常难以理解的,但我觉得必须有一个更清洁的方式。
答案 0 :(得分:13)
我认为这非常难以理解
是的,但您可以通过将其封装到辅助方法中来解决这个问题。如果您将其称为Where
,您将获得所需的语法:
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, Task<bool>> predicate)
{
return source.SelectMany(async item => new
{
ShouldInclude = await predicate(item),
Item = item
})
.Where(x => x.ShouldInclude)
.Select(x => x.Item);
}
答案 1 :(得分:2)
或者,您可以使用以下内容:
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, Task<bool>> predicate)
{
return source.SelectMany(item =>
predicate(item).ToObservable()
.Select(include => include ? Observable.Return(item) : Observable.Empty<T>())
);
}
基本上Where
如何运作,如果你用SelectMany来定义它:
public static IObservable<T> Where<T>(
this IObservable<T> source, Func<T, bool> predicate)
{
return source.SelectMany(item => predicate(item) ? Observable.Return(item) : Observable.Empty<T>());
}
实际上,@ svick的答案有更少的关闭。 :)