C#::何时使用事件或从事件处理接口派生的对象集合?我认为这是一个简单的“问题”,我找到了几个解决方案,但我不知道哪种方法是C#中的最佳实践。在应用程序的生命周期中,我有一个主要对象(比如一个单例)。这个“MasterClass”创建了一堆新类型的对象,每次调用MasterClass.Instance.CreateSlaveObject时都会说“SlaveClass”。这个MasterClass还监视其他一些对象的状态变化,当这种情况发生时,通知它创建的SlaveClass对象这个变化。看起来很简单。由于我来自原生C++世界,我首先使用它来创建一个接口InterfaceIChangeEventListener{voidChangeHappened();我从中派生了“SlaveClass”。然后在我的“MasterClass”中我有:...IListslaveList;...CreateSlaveObject{...slaveList.Add(slave);}...ChangeHappened(){...foreach(slaveList中的slave){slave.ChangeHappened();这行得通。但我一直想知道是否有另一种(更好的)方法来做到这一点。因此,我对这个主题进行了更多研究,并看到了C#事件。因此,我不是在MasterClass中维护一个从属集合,而是将MasterClass注入到SlaveClass的构造函数中(或通过属性),并让SlaveClass对象将其ChangeHappened添加为事件处理程序。这会说:...Master...publicdelegatevoidChangeHappenedDelegate(objectsender,NewsInfoArgsargs);公共事件NewUpdateDelegateChangeHappenedEvent;....publicSlaveClass(MasterClasspublisher)//注入发布者服务{publisher.ChangeHappenedChangeEvent+=;但这似乎是Slave和Master之间不必要的耦合,但我喜欢提供的内置事件通知机制的优雅。那么我应该保留我当前的代码,还是转向基于事件的方法(使用发布者注入)?为什么?或者,如果您可以提出我可能错过的替代解决方案,我也将不胜感激。好吧,在我看来,像您展示的事件和界面是同一枚硬币的两个面(至少在您描述的上下文中),但它们实际上是两个面。我对事件的看法是“我需要订阅您的事件,因为我需要您在事件发生时告诉我”。接口方式是“我需要在你身上调用一个方法来通知你发生了什么事”。这听起来可能是一样的,但它是在和不同的人交谈,在这两种情况下,你所说的都是“大师班”,这让一切都不同了。请注意,如果您的从类有一个方法,当主类发生某些事情时将被调用,那么您不需要包含代码来挂钩它,您可以在CreateSlaveClass方法中轻松地执行此操作:SlaveClasssc=new从类();ChangeHappenedEvent+=sc.ChangeHappened;返回sc;这将基本上使用事件系统,但让MasterClass代码完成事件的所有连接。SlaveClass对象和单例类一样长吗?如果不是,那么您需要处理它以防它们变得陈旧/不再需要,如上述情况(基本上在您和我的情况下),您在MasterClass中持有对这些对象的引用,因此它们永远不会有资格成为垃圾除非您强行删除这些事件或注销接口。要解决SlaveClass与MasterClass不同的问题,您将遇到与您在评论中指出的相同的耦合问题。“处理”(注意引号)的一种方法可能不是真正直接链接到SlaveClass对象上的正确方法,而是创建一个将在内部调用此方法的包装器对象。这样做的好处是包装器对象可以在内部使用Wea??kReference对象,这样一旦你的SlaveClass对象符合垃圾收集条件,它就可能被收集,然后下次你尝试调用它的正确方法时,你将注意这一点,所以你必须清理。例如,像这样(这里我在没有使用VisualStudio智能感知和编译器的情况下键入,请理解这段代码的含义,而不是语法(错误)。)publicclassWrapperClass{privateWeakReference_Slave;publicWrapperClass(SlaveClassslave){_Slave=newWeakReference(slave);}publicWrapperClass.ChangeHappened(){Objecto=_Slave.Target;如果(o!=null)((SlaveClass)o).ChangeHappened();elseMasterClass.ChangeHappenedEvent-=ChangeHappened;在你的MasterClass中你会这样做:SlaveClasssc=newSlaveClass();WrapperClasswc=newWrapperClass(sc);ChangeHappenedEvent+=wc.ChangeHappened;返回sc;在收集到SlaveClass对象后,从MasterClass到事件处理程序的下一次调用(但不早于此事件)通知他们发生了变化,所有那些不再有对象的包装器将被删除。我认为这只是个人喜好问题……我个人喜欢使用事件,因为它更符合.NET“哲学”。在您的情况下,如果MasterClass是单例,则无需将其传递给SlaveClass的构造函数,因为可以使用单例属性(或方法)检索它:publicSlaveClass(){MasterClass.Instance.ChangeHappenedEvent+=发生变化;既然你似乎有一个MasterClass的单例实例,你为什么不订阅MasterClass.Instance.ChangeHappenedEvent?它仍然是一个紧耦合,但相对整洁。虽然事件是公开订阅/取消订阅功能的常见做法,但在不需要公开订阅/取消订阅功能的许多情况下,它们并不是最佳实践。在这种情况下,唯一允许订阅/取消订阅事件的事件是您自己创建的事件,因此不需要公共订阅/取消订阅方法。此外,主人对奴隶的了解远远超过典型的事件发布者对订阅者的了解。所以我赞成让主人明确处理订阅的连接/断开连接。我可能会添加一个功能,通过主从之间的耦合使某些功能更容易,如果所有外部引用都被删除,则允许对从属进行垃圾收集。执行此操作的最简单方法可能是让主服务器为从服务器保留一个“WeakReference”列表。当需要通知slave发生了什么事时,遍历列表,取消引用任何仍然存在的WeakReference,并通知slave。如果列表中超过一半的项目是自上次扫描后添加的,并且列表包含至少250个左右的项目,则将所有实时引用复制到新列表并替换旧列表。避免必须取消引用Wea??kReference对象的另一种方法是让公共“从属”对象成为私有对象的包装器,让公共对象覆盖Finalize,并让私有对象知道不存在对它的外部引用。这将需要为对象的公共访问添加额外的强间接级别,但它会避免创建(即使是暂时的)对废弃对象的强引用。以上是C#学习教程:C#::Whentouseeventsorcollectionsofobjectsderivedfromeventhandlinginterfaces?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
