为什么要订阅甚至创建一个从不产生任何结果、甚至不产生错误或完成的可观察对象?
它是可观察事件流组成中的一个基本"原子",出现在各种情况下,但Observable.Never
在实践中最常见的用途之一是编写测试。例如,它很容易实现对超时逻辑的健壮检查,并且在测试场景中经常与TestScheduler
或其他虚拟时间调度器相结合。如果你检查Rx本身的源代码,你会发现它出现在许多单元测试中。
我看到它与Observable.Window和Observable.Buffer一起用于关闭Observable。这是一个微不足道的例子,因为实际的代码太复杂了,无法发布。
static IObservable<Unit> CloseWindow(int interval)
{
if (interval <= 0)
{
return Observable.Never<Unit>();
}
return Observable.Interval(TimeSpan.FromSeconds(interval)).Select(_ => Unit.Default);
}
在为分析员分组数据时使用,有时需要所有数据,有时不需要。再举一个琐碎的例子
static IObservable<double> AverageOfWindow(IObservable<int> source, int interval)
{
return source.Buffer(CloseWindow(interval)).Select(o => o.Average());
}
如果使用Empty,它将永远不会产生结果,而使用never,它基本上是通过传递Buffer和Window方法。可以在不需要时编写可观察到的跳过缓冲区,但如果CloseWindow具有确定何时关闭缓冲区序列的所有逻辑,则维护起来更容易,代码更少。同样,在这个例子中,它很琐碎,但在实际代码中,决定缓冲区何时关闭的逻辑更复杂。
我自己也考虑过这个问题。我得出的结论是,你依赖的框架会使用这个(或者,如果你正在创建一个框架,你会使用这个)。我认为它相当于一个空的IEnumerable
。考虑这样一种情况,即调用一个返回IEnumerable
的方法。也许从该方法返回的IEnumerable
取决于传递给该方法的参数;在某些情况下可能没有要返回的数据。一些人们(我在这里纠结了几个选择词)可能会返回null
,但更开明的开发人员会返回一个空的IEnumerable
。我看到一个从不产生任何东西的可观察物等价于一个空的IEnumerable
。当然,你可以认为Observable.Empty
(它返回一个立即完成的可观察对象)实际上相当于一个空的IEnumerable
,但我认为这可能取决于情况。无论是谁在设计框架,都必须决定哪个在语义上是正确的,Observable.Empty
还是Observable.Never
。
那是我的2美分。也许有人会有更好的理由。