Как вы устанавливаете, должен ли метод возвращать IEnumerable<T>
или IObservable<T>
?
Почему я должен выбрать одну парадигму над другой?
Как вы устанавливаете, должен ли метод возвращать IEnumerable<T>
или IObservable<T>
?
Почему я должен выбрать одну парадигму над другой?
IEnumerable<T>
T
'sIObservable<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>)
T
получает "push" от IObservable<T>
, он отправляется в очередь.T
из IEnumerable<T>
, он блокирует до тех пор, пока очередь не будет пустой, а затем удалит.IEnumerable<T>
до IObservable<T>
Если что-то естественно IEnumerable<T>
, но вы хотите обработать его, как если бы это был IObservable<T>
, вы можете сделать это с помощью этого метода:
IObservable<T> Observable.ToObservable(this IEnumerable<T>)
T
из IEnumerable<T>
.T
, он "подталкивает" его к вам через IObservable<T>
. IObservable<T>
- это специализированный интерфейс, который можно использовать для pub/sub и других других шаблонов. Вы знаете, когда вам нужно вернуть IObservable<T>
, поэтому, если нет конкретной необходимости, верните IEnumerable<T>
.
Обновить вопрос в комментарии
В принципе, IObservable<>
использует механизм "Push", а IEnumerable < > использует механизм "Pull". Если вы собираетесь просто получить список данных, которые не нужно уведомлять подписчиков об изменениях (push), вы можете использовать IEnumerable
. Если подписчик (Window, Control, другие клиентские программы/подпрограммы и т.д.) Должен знать, когда данные были изменены, используйте IObservable<>
. Одним из примеров является использование IObservable
для обновления основного потока пользовательского интерфейса в программе Windows из дочернего потока (обычно это невозможно сделать без фантазийной работы). Читайте об .NET Reactive Extensions (Rx.NET).
Используйте IObservable<T>
, если вы хотите поместить данные вызывающим абонентам вашего метода в удобное для вас время. Вы делаете это, вызывая OnNext()
on Observers
, зарегистрированный интерес через Subscribe()
.
Используйте IEnumerable<T>
, если вы хотите, чтобы вызывающие абоненты вашего метода извлекали данные по своему усмотрению. Они делают это, вызывая GetEnumerator()
для получения IEnumerator
и вызывая MoveNext()
и Current
(foreach
для компиляции).
UPDATE: возможно, лучше всего привести несколько примеров:
Функция, которая возвращает валютные цены в банке, является хорошим кандидатом для IObservable<T>
. Здесь информация имеет критический момент. Как сервер этих данных, вам нужно как можно скорее отправить его клиенту. Клиент не будет знать, когда эти данные будут готовы. Поэтому вы подталкиваете их к ним.
Функция, которая возвращает действительные торговые дни для определенного финансового инструмента и используется для заполнения дней отключения электроэнергии в календарном контроле, является хорошим кандидатом для IEnumerable. Эти данные редко меняются, и клиент (настройка элемента управления) предпочитает потреблять его в темпе, который он диктует.
Используйте IEnumerable<T>
для представления списков, используйте IObservable<T>
для представления событий. Легкий peasy.