何时使用IEnumerable和IObservable

本文关键字:IObservable IEnumerable 何时使 | 更新日期: 2023-09-27 18:18:05

如何确定一个方法是否应该返回IEnumerable<T>IObservable<T> ?

为什么我要选择一个范式而不是另一个呢?

何时使用IEnumerable和IObservable

Types

  • IEnumerable<T>
    • 你反复从T序列中"拉"出
  • IObservable<T>
    • T序列正在被"推送"给你

为什么我要选择一个范式而不是另一个呢?

你通常"选择"一个范例而不是另一个。通常,其中一个自然会脱颖而出,成为正确的选择,而另一个则没有任何意义。

<标题> 例子

考虑以下例子:

  • 一个巨大的CSV文本文件每行都有一个项目,你想一次处理一个,而不是一次将整个文件加载到内存中:IEnumerable<List<string>>

  • 您正在运行HTTP web服务器:IObservable<WebRequest>

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

  • 您正在响应用户界面按钮点击:IObservable<Click>

在这些例子中(特别是IObservable<T>的例子),使用其他类型是没有意义的。

但是如果我想使用"other"类型呢…

IObservable<T> to IEnumerable<T>

如果某些内容自然是IObservable<T>,但你想把它当作IEnumerable<T>来处理,你可以使用这个方法:

IEnumerable<T> Observable.ToEnumerable(this IObservable<T>)
  • TIObservable<T>"推送"时,它被发送到队列中。
  • 当你试图从IEnumerable<T>中"拉"出T时,它会阻塞,直到队列不空,然后退出队列。

IEnumerable<T> to IObservable<T>

如果某些内容自然是IEnumerable<T>,但你想把它当作IObservable<T>来处理,你可以使用这个方法:

IObservable<T> Observable.ToObservable(this IEnumerable<T>)
    . net线程池中的线程将反复尝试从IEnumerable<T>中"拉"出T
  • 每次它"拉"一个T,它通过IObservable<T>"推"给你。

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

使用IEnumerable<T>如果你想让你的方法的调用者提取数据在他们方便。他们通过调用GetEnumerator()来获取IEnumerator,并调用MoveNext()Current (foreach编译成这个)来实现这一点。

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

返回银行货币价格的函数是IObservable<T>的一个很好的候选函数。这里的信息是时间关键的。作为该数据的服务器,您需要尽快将其传送到客户端。客户端将不知道数据何时准备好。所以你把它推给他们。

返回特定金融工具的有效交易日并用于填充日历控件上的停电日的函数是IEnumerable的一个很好的候选函数。该数据很少更改,并且客户端(设置控件)更喜欢以指定的速度使用它。

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

更新评论中的问题

基本上,IObservable<>使用"Push"机制,IEnumerable<>使用"Pull"机制。如果您只想获取数据列表,而不需要将更改通知订阅者(推送),那么您可以使用IEnumerable。如果订阅者(Window, Control,其他客户端程序/例程等)需要知道数据何时更改,则使用IObservable<>。一个例子是使用IObservable从子线程更新windows程序中的主UI线程(通常这不能没有花哨的脚法完成)。阅读。net响应式扩展(Rx.NET)

IEnumerable<T>表示列表,用IObservable<T>表示事件。容易peasy。