Подтвердить что ты не робот

Когда использовать IEnumerable vs IObservable?

Как вы устанавливаете, должен ли метод возвращать IEnumerable<T> или IObservable<T>?

Почему я должен выбрать одну парадигму над другой?

4b9b3361

Ответ 1

Типы

  • IEnumerable<T>
    • Вы повторно "тянете" из последовательности T 's
  • IObservable<T>
    • Последовательность T подталкивается к вам

Почему я должен выбрать одну парадигму над другой?

Обычно вы не выбираете одну парадигму над другой. Обычно один выделяется естественно как правильный выбор, а другой не имеет никакого смысла.

Примеры

Рассмотрим следующие примеры:

  • Огромный текстовый файл CSV имеет элемент в каждой строке, и вы хотите обрабатывать их по одному, не загружая сразу весь файл: IEnumerable<List<string>>

  • У вас работает веб-сервер HTTP: IObservable<WebRequest>

  • Вы хотите получить узлы структуры данных дерева в ширину: IEnumerable<Node>

  • Вы отвечаете на нажатия кнопок пользовательского интерфейса: IObservable<Click>

В каждом из этих примеров (особенно случаев IObservable<T>) просто не имеет смысла использовать другой тип.

Но что, если я хочу использовать "другой" тип...

IObservable<T> до IEnumerable<T>

Если что-то естественно IObservable<T>, но вы хотите обработать его, как если бы это был IEnumerable<T>, вы можете сделать это с помощью этого метода:

IEnumerable<T> Observable.ToEnumerable(this IObservable<T>)
  • Когда a T получает "push" от IObservable<T>, он отправляется в очередь.
  • Когда вы пытаетесь "вытащить" T из IEnumerable<T>, он блокирует до тех пор, пока очередь не будет пустой, а затем удалит.

IEnumerable<T> до IObservable<T>

Если что-то естественно IEnumerable<T>, но вы хотите обработать его, как если бы это был IObservable<T>, вы можете сделать это с помощью этого метода:

IObservable<T> Observable.ToObservable(this IEnumerable<T>)
  • Нить из пула потоков .NET будет неоднократно пытаться "вытащить" T из IEnumerable<T>.
  • Каждый раз, когда он "тянет" T, он "подталкивает" его к вам через IObservable<T>.

Ответ 2

IObservable<T> - это специализированный интерфейс, который можно использовать для pub/sub и других других шаблонов. Вы знаете, когда вам нужно вернуть IObservable<T>, поэтому, если нет конкретной необходимости, верните IEnumerable<T>.

Обновить вопрос в комментарии

В принципе, IObservable<> использует механизм "Push", а IEnumerable < > использует механизм "Pull". Если вы собираетесь просто получить список данных, которые не нужно уведомлять подписчиков об изменениях (push), вы можете использовать IEnumerable. Если подписчик (Window, Control, другие клиентские программы/подпрограммы и т.д.) Должен знать, когда данные были изменены, используйте IObservable<>. Одним из примеров является использование IObservable для обновления основного потока пользовательского интерфейса в программе Windows из дочернего потока (обычно это невозможно сделать без фантазийной работы). Читайте об .NET Reactive Extensions (Rx.NET).

Ответ 3

Используйте IObservable<T>, если вы хотите поместить данные вызывающим абонентам вашего метода в удобное для вас время. Вы делаете это, вызывая OnNext() on Observers, зарегистрированный интерес через Subscribe().

Используйте IEnumerable<T>, если вы хотите, чтобы вызывающие абоненты вашего метода извлекали данные по своему усмотрению. Они делают это, вызывая GetEnumerator() для получения IEnumerator и вызывая MoveNext() и Current (foreach для компиляции).

UPDATE: возможно, лучше всего привести несколько примеров:

Функция, которая возвращает валютные цены в банке, является хорошим кандидатом для IObservable<T>. Здесь информация имеет критический момент. Как сервер этих данных, вам нужно как можно скорее отправить его клиенту. Клиент не будет знать, когда эти данные будут готовы. Поэтому вы подталкиваете их к ним.

Функция, которая возвращает действительные торговые дни для определенного финансового инструмента и используется для заполнения дней отключения электроэнергии в календарном контроле, является хорошим кандидатом для IEnumerable. Эти данные редко меняются, и клиент (настройка элемента управления) предпочитает потреблять его в темпе, который он диктует.

Ответ 4

Используйте IEnumerable<T> для представления списков, используйте IObservable<T> для представления событий. Легкий peasy.