在IObservable <T>接口中返回IDisposable的目的是什么?

Ada*_*eck 15 c# design-patterns idisposable system.reactive observer-pattern

我正在阅读Head First Design Patterns一书,并尽力将代码从Java转换为C#.在本书讨论了观察者模式后,它提到Java内置了类/接口,.NET4也是如此.所以我开始研究如何正确使用它,除了Subscribe()方法之外,我已经找到了大部分内容.

如果您在尝试订阅IObserver时查看MSDN文章,该方法将返回IDisposable.为什么这是必要的?为什么不实现一个基于方法参数取消下载IObserver的方法?我研究了使用IDisposable接口的原因.我也读过这篇文章,但不太了解差异/它试图告诉我的内容:

它返回对IDisposable接口的引用.这使观察者能够在提供者完成发送之前取消订阅(即停止接收通知),并调用订阅者的OnCompleted方法.

sup*_*cat 8

取消订阅所需的信息将根据事件发布者管理订阅的方式而有所不同.用于事件的Remove方法- 传递给委托先前传递给Add方法的方法 - 有点可行,但有一些重大缺陷.其中:

  1. 通常需要事件发布者执行线性搜索以查找包含与订阅相关的信息的记录.如果事件可能有许多订阅者,则可能会不必要地创建O(N ^ 2)行为.如果订阅者保存在某种链接列表(链接对象或索引链接数组插槽)中,并且取消订阅请求保存有关要取消的订阅的信息,则订阅和取消订阅都可以在恒定时间内处理.此外,可以安全,轻松地以无锁无阻塞的方式处理取消订阅(使用一个`CompareExchange`,最有可能是无争议的数组插槽),可以在`Finalize`上下文中安全地完成.
  2. 如果一个代表多次订阅处理顺序的事件,并且代码试图取消第一个订阅,则最后一个订阅将被取消,第一个订阅将保持有效.
  3. 如果订阅了委托"D",则订阅包含"A","B","C"和"D"的多播委托"ABCD",然后"D"取消订阅,然后委托"DABC"将保留即使代码试图取消订阅"ABCD",也会按顺序订阅.请注意,如果使用`List`而不是`delegateType.Combine`,可以避免这个问题,但其他问题仍然存在.

使用事件订阅方法返回可用于取消订阅的对象可避免这些问题.那么最大的问题就是应该使用什么类型的对象.我想到了三个选择:

  1. 代表(可能无参数,返回`void`)
  2. 一些`ICancelSubscription`接口,使用单个方法(可能是无参数的,返回`void`)来取消订阅
  3. `IDisposable`,一个存在的接口,具有单个无参数方法,并广泛用于与清理相关的目的

使用代表是一个合理的选择.它可以很容易地封装取消订阅所需的任何信息,而用户不必担心该信息可能采取何种形式.使用委托将需要分配至少一个额外的堆对象(对于委托本身)和可能两个(第二个是包含取消订阅信息的对象).使用IDisposable将与使用委托基本相同,除了一个人会调用Dispose而不是Invoke; 但是,在许多情况下,IDisposable在效率方面会略有优势.使用其他一些界面也是可行的,但与使用现有界面相比,它不会提供任何优势IDisposable.