简体   繁体   中英

When to use IEnumerable vs IObservable?

How do you establish whether or not a method should return IEnumerable<T> or IObservable<T> ?

Why would I choose one paradigm over the other?

Types

  • IEnumerable<T>
    • You repeatedly "pull" from a sequence of T 's
  • IObservable<T>
    • A sequence of T 's is being "pushed" at you

Why would I choose one paradigm over the other?

You typically don't "choose" one paradigm over the other. Usually one stands out naturally as the correct choice, with the other one not making any sense.

Examples

Consider the following examples:

  • A huge CSV text file has an item on each line, and you want to process them one at a time without loading the entire file into memory at once: IEnumerable<List<string>>

  • You are running an HTTP web server: IObservable<WebRequest>

  • You want to do get the nodes of a tree data structure in a breadth-first manner: IEnumerable<Node>

  • You are responding to user interface button clicks: IObservable<Click>

In each of these examples (especially the IObservable<T> cases), it just wouldn't make sense to use the other type.

But what if I want to use the "other" type...

IObservable<T> to IEnumerable<T>

If something is naturally an IObservable<T> but you want to process it as if it were an IEnumerable<T> , you can do that with this method:

IEnumerable<T> Observable.ToEnumerable(this IObservable<T>)
  • When a T gets "pushed" by the IObservable<T> , it gets sent into a queue.
  • When you try to "pull" a T out of the IEnumerable<T> , it blocks until the queue isn't empty, then dequeues.

IEnumerable<T> to IObservable<T>

If something is naturally an IEnumerable<T> but you want to process it as if it were an IObservable<T> , you can do that with this method:

IObservable<T> Observable.ToObservable(this IEnumerable<T>)
  • A thread from the .NET thread pool will repeatedly try to "pull" a T from the IEnumerable<T> .
  • Each time it "pulls" a T , it "pushes" it at you via the IObservable<T> .

Use IObservable<T> if you want to push data to callers of your method at your convenience . You do this by calling OnNext() on Observers that registered interest via Subscribe() .

Use IEnumerable<T> if you want callers of your method to pull data at their convenience . They do this by calling GetEnumerator() to acquire an IEnumerator and calling MoveNext() and Current ( foreach compiles to this).

UPDATE: Perhaps best to give some examples:

A function that returns currency prices in a bank is a good candidate for IObservable<T> . Here the information is time-critical. As the server of this data, you need to get it to the client as soon as possible. The client won't know when that data is ready. So you push it to them.

A function that returns the valid trading days for a particular financial instrument and is used to populate the blackout days on a calendar control is a good candidate for IEnumerable. This data rarely changes and the client (setting up the control) prefers to consume it at a pace it dictates.

IObservable<T> is a specialized interface that can be used for pub/sub and various other patterns. You would know when you needed to return an IObservable<T> , so if there is not specific need then return IEnumerable<T> .

Update to question in comment

Basically, IObservable<> uses a "Push" mechanism and IEnumerable<> uses a "Pull" mechanism. If you are going to simply obtain a list of data that doesn't need to notify subscribers of changes (push) then you can use IEnumerable . If a subscriber (Window, Control, other Client programs/routines, etc...) needs to know when data changed then use IObservable<> . One example is using IObservable to update the main UI thread in a windows program from a child thread (Normally this cannot be done without fancy footwork. Read up on .NET Reactive Extensions (Rx.NET).

Use IEnumerable<T> to represent lists, use IObservable<T> to represent events. Easy peasy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM