在IDiposable类的Dispose方法中注销外部事件是一种好习惯吗?我阅读了解释如何使用Dispose模式及其工作方式的优秀答案。正确使用IDisposable接口该帖子明确指出您希望在两种不同的情况下使用Dispose模式:摆脱非托管资源(因为我们必须这样做)摆脱托管资源(因为我们想提供帮助)我的问题是:是的你应该。这是向您的类的使用者表明它具有必须发布的“资源”的最佳方式。(即使事件订阅在技术上不是资源)在许多(大多数?)情况下,对象在调用Dispose后不久就可以进行垃圾回收。例如,对于使用using语句实例化的IDisposable对象,这始终为真:此处符合垃圾收集条件在这种情况下,我个人一般不会在删除事件订阅时弄乱代码。例如,ASP.NETPage或UserControl是IDisposable,通常处理来自网页上其他控件的事件。处理Page或UserControl时无需删除这些事件订阅,事实上我从未见过执行此操作的ASP.NET应用程序。更新其他回答者建议您始终取消订阅IDisposable类的Dispose方法中的事件。总的来说,我不同意这一点,尽管可能存在特定于应用程序的情况。合乎逻辑的结论是任何订阅事件的类都应该是IDisposable的,这样它就可以确定地取消订阅——我看不出为什么这个建议只适用于碰巧拥有非托管资源的类的合理理由。我不认为这是好的一般性建议,原因如下:我更喜欢双管齐下的方法:(1)UnregisterFromExternalEvents()的显式方法;UnregisterFromExternalEvents();(2)在Dispose()中调用该方法。这样,任何控制该类实例的代码都可以显式注销它,或者信任Dispose来正确处理和处置此类事情。是的,取消注册所有外部事件被认为是一种好的做法,但由于事件的松耦合性质,这并不是绝对必要的。它从事件生成器中删除订阅者对象的事件入口点引用,yes会有所帮助。取消订阅处理程序方法的一部分也可以。Dispose方法的经验法则是-“Dispose方法应该卸载资源,如果多次调用dispose它仍然有效,即你应该释放资源只处理一次。(这需要在处理之前进行检查资源)”是的,这是一个非常好的主意。事件发布者持有对事件订阅者的引用,这可以防止订阅者被垃圾收集。(请参阅事件处理程序是否会阻止垃圾收集的发生?)此外,如果事件处理程序使用您正在发布的资源,则事件处理程序(事件发布者将继续调用它们)可能会在资源被释放后生成异常。因此,在释放资源之前注销任何事件非常重要,尤其是在使用异步或多线程时,因为在某些情况下,可能会在释放资源和注销该事件之间引发事件。.以下代码显示了这一点:usingSystem;使用System.Collections.Generic;使用System.Linq;使用系统文本;namespaceReleaseEvents{classProgram{publicstaticeventEventHandlerSomethingHappened;staticvoidMain(string[]args){使用(varl_dependent=newDependent()){SomethingHappened(null,EventArgs.Empty);}//只是为了证明这一点,垃圾回收//不会清理依赖对象,即使//它已被释放。GC.收集();try{//此调用将导致已处置的对象//(仍注册到事件中)//抛出异常。SomethingHappened(null,EventArgs.Empty);}catch(InvalidOperationExceptione){Console.ForegroundColor=ConsoleColor.Red;Console.WriteLine(e.ToString());}Console.ReadKey(true);}}classDependent:IDisposable{私有对象_resource;publicDependent(){Program.SomethingHappened+=Program_SomethingHappened;_resource=新对象();}私人无效编ram_SomethingHappened(objectsender,EventArgse){if(_resource==null)thrownewInvalidOperationException("Resourcecannotbenull!");Console.WriteLine("SomethingHappened处理成功!");}publicvoidDispose(){_resource=null;}}}Dependent类将在第二次引发SomethingHappened事件时抛出InvalidOperationException您必须取消注册该事件以防止这种情况发生:classDependent:IDisposable{//...publicvoidDispose(){Program.SomethingHappened-=Program_SomethingHappened;_资源=空;我在第一次尝试实现MVVM架构时遇到了这个问题。当我在ViewModel之间切换时,我刚刚发布了我认为是唯一的参考(ActiveViewModel属性)。我没有意识到的是,我的ViewModel订阅的事件将它保存在内存中。随着应用程序运行时间的延长,它会变得越来越慢。最终我意识到我认为我正在发布的ViewModel实际上是在继续处理事件(昂贵)。我必须显式释放事件处理程序来解决这个问题。感谢您的提问,我会这样写我的课程:以上是C#学习教程:在IDiposable类的Dispose方法中取消注册外部事件是否是一种好习惯?如果分享的内容对你有用,需要了解更多C#学习教程,希望你多多关注——classFoo:IDisposable{publiceventEventHandlerMyEvent;//////当取消订阅所有事件时///publicvoidDispose(){if(MyEvent!=null){foreach(DelegatedelinMyEvent.GetInvocationList())MyEvent-=(delasEventHandler);}//对类中的任何其他事件做同样的操作//....}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
