旧版本的响应式扩展为IEnumerable提供了Run和Do扩展方法。他们似乎在做完全相同的事情,我不确定有什么不同。
我问这个问题是因为我正在升级一些旧代码,Do已经被转移到Ix(这还不是一个稳定的版本),看起来Run已经被ForEach取代了。
Do指定执行时会产生一些副作用,并返回带有副作用的序列。
Run枚举序列,并返回void。
可以这样想:"标记"具有副作用的序列。这些副作用只有在枚举序列时才会发生。Do返回带有副作用的新序列。
// Example of .Do
var elements = new[] { 1, 2, 3 };
var elementsWithSideEffects = elements.Do(e => MessageBox.Show(e)); // No Message Boxes shown yet!
elementsWithSideEffects.Run(); // 3 message boxes shown
另一方面,Run枚举序列:Run(),或者可选地附加副作用,然后枚举序列:Run(action)
// Example of .Run with its own side effects:
var elements = new[] { 1, 2, 3 };
elements.Run(e => MessageBox.Show(e)); // 3 Message Boxes shown.
您可以将Do
视为"Peek",因为它对每个值/错误/完成执行副作用,但不能更改它们的值,因为传递的lambda都返回void。它类似于Subscribe
,但它不会打破单子("链"),因为它返回IObservable<T>
。Do
常用于日志记录。
Run
基本上是Subscribe
的阻塞版本,这意味着执行不会继续超过该行,直到OnComplete/OnError被调用。
把Do想象成一个安培计:你切断电路(查询操作符链),并为电流(通过查询操作符的值)连接一个仪表(操作委托)。对于流经电路(查询)的每一个电子(值),仪表(动作)都要做功。注意,电路(查询)仍然未通电(惰性)。直到您插入电池(运行foreach循环),电流(值)才开始流动。打开电路(运行查询)的一种简单方法是使用一个蓄电池(ForEach操作符)。
Do的行为就像其他LINQ操作符,如Select或Where——如果你只是使用它,什么也不会发生,你必须要foreach
才能发生一些事情。Run/ForEach/Subscribe的行为类似于foreach
语句,它立即执行。
如果你不是100%清楚什么时候使用每一个,避免使用Do,只使用ForEach/Run。