何时使用IEnumerable vs IObservable?

如何确定方法是否应该返回IEnumerableIObservable

为什么我会选择一种范式而不是另一种?

类型

  • IEnumerable
    • 你反复从一系列T “拉”出来
  • IObservable
    • 一系列T被“推”给你

为什么我会选择一种范式而不是另一种?

你通常不会 “选择”一种范式而不是另一种范式。 通常一个人自然而然地脱颖而出作为正确的选择,另一个人没有任何意义。

例子

请考虑以下示例:

  • 一个巨大的CSV文本文件在每一行上都有一个项目,您希望一次处理一个项目而不立即将整个文件加载到内存中: IEnumerable>

  • 您正在运行HTTP Web服务器: IObservable

  • 您希望以广度优先的方式获取树数据结构的节点: IEnumerable

  • 您正在响应用户界面按钮单击: IObservable

在每个示例中(特别是IObservable情况),使用其他类型是没有意义的。

但是,如果我想使用“其他”类型怎么办…

IObservableIEnumerable

如果某些东西自然是IObservable但你想要像处理IEnumerable那样处理它,你可以用这个方法做到这一点:

 IEnumerable Observable.ToEnumerable(this IObservable) 
  • TIObservable “推”时,它会被发送到队列中。
  • 当您尝试从IEnumerable “拉出” T时,它会阻塞直到队列不为空,然后出列。

IEnumerableIObservable

如果某些内容自然是IEnumerable但您想要将其处理为IObservable ,则可以使用此方法执行此操作:

 IObservable Observable.ToObservable(this IEnumerable) 
  • 来自.NET线程池的线程将反复尝试从IEnumerable “拉” T
  • 每次它“拉”一个T ,它就会通过IObservable “推”它。

如果要在方便时 数据送到方法的调用者,请使用IObservable 。 您可以通过在通过Subscribe()注册兴趣的Observers上调用OnNext()来完成此操作。

如果您希望方法的调用者在方便时 提取数据请使用IEnumerable 。 他们这样做是通过调用GetEnumerator()来获取IEnumerator并调用MoveNext()Currentforeach编译为此)。

更新:也许最好给出一些例子:

返回银行货币价格的函数是IObservable的理想选择。 这里的信息对时间至关重要。 作为此数据的服务器,您需要尽快将其发送到客户端。 客户端将不知道该数据何时准备就绪。 所以你把它推给他们。

返回特定金融工具的有效交易日并用于填充日历控件上的停电天数的函数是IEnumerable的良好候选者。 这些数据很少改变,客户端(设置控件)更喜欢按照它指示的速度消耗它。

IObservable是一个专用接口,可用于pub / sub和各种其他模式。 您将知道何时需要返回IObservable ,因此如果没有特定需要,则返回IEnumerable

更新评论中的问题

基本上, IObservable<>使用“推”机制,IEnumerable <>使用“拉”机制。 如果您只是想获得一个不需要通知订户更改(推送)的数据列表,那么您可以使用IEnumerable 。 如果订户(窗口,控制,其他客户端程序/例程等)需要知道数据何时更改,则使用IObservable<> 。 一个例子是使用IObservable从子线程更新Windows程序中的主UI线程(通常,如果没有花哨的步法,这是不可能完成的。阅读.NET Reactive Extensions(Rx.NET)。

使用IEnumerable表示列表,使用IObservable表示事件。 十分简单。