当前位置: 首页 > 编程语言 > C#

C#事件处理(对比Java)分享

时间:2023-04-11 11:47:05 C#

C#事件处理(对比Java)我目前在C#中使用delagates,很难理解和实现事件。我习惯了Java的做事方式:为包含许多方法定义的侦听器类型定义一个接口如果我对侦听器中定义的所有事件不感兴趣,为该接口定义一个适配器类使事情变得更容易在类中定义Add、Remove和Get[]方法以引发事件在c#中完全相同,但似乎有一个用于c#的新(更好?)系统。在阅读了无数解释c#中委托和事件使用的教程之后,我仍然无法真正理解这是怎么回事:S简而言之,我将如何在c#中为以下方法实现一个事件系统:voidcomputerStarted(Computercomputer);voidcomputerStopped(计算机计算机);voidcomputerReset(计算机计算机);voidcomputerError(计算机计算机,异常错误);^以上方法取自我曾经做过的一个Java应用程序,我正在尝试将其移植到c#。太感谢了!您将创建四个事件,以及引发它们的方法,以及一个新的基于EventArgs的类来指示错误:publicclassExceptionEventArgs:EventArgs{publicExceptionEventArgs(Exceptionerror){this.error=error;}publicError{get{返回错误;}}}publicclassComputer{publiceventEventHandlerStarted=delegate{};公共事件EventHandlerStopped=delegate{};公共事件EventHandlerReset=delegate{};公共事件EventHandlerError=delegate{};protectedvoidOnStarted(){Started(this,EventArgs.Empty);}protectedvoidOnStopped(){Stopped(this,EventArgs.Empty);}protectedvoidOnReset(){Reset(this,EventArgs.Empty);}protectedvoidOnError(Exceptione){Error(this,newExceptionEventArgs(e));然后类将使用方法或匿名函数订阅事件:someComputer.Started+=StartEventHandler;//一个方法someComputer.Stopped+=delegate(objecto,EventArgse){Console.WriteLine("{0}hasstarted",o);};someComputer.Reset+=(o,e)=>Console.WriteLine("{0}hasbeenreset");关于上面的一些注意事项:有关事件的更多详细信息,请参阅我的事件/委托文章YouhavetodefineadelegateforthispublicdelegatevoidComputerEvent(objectsender,ComputerEventArgse);ComputerEventArgs将定义如下:classComputerEventArgs:EventArgs{//TODO包装在属性中){}}触发事件的类将包含以下内容:publicYourClass{...publiceventComputerEventComputerStarted;publiceventComputerEventComputerStopped;publiceventComputerEventComputerReset;publiceventComputerEventComputerError;...}这就是您分配的方式事件处理程序:YourClassobj=newYourClass();obj.ComputerStarted+=newComputerEvent(your_computer_started_handler);你的处理程序是:privatevoidComputerStartedEventHandler(objectsender,ComputerEventArgse){//做你的事。主要区别在于,在C#中,事件不是基于接口的。相反,事件发布者声明您可以将其视为函数指针的委托(尽管不完全相同:-))。然后,订阅者将事件原型作为常规方法实现,并将该委托的新实例添加到发布者的事件处理程序链中。阅读有关代表和事件的更多信息。您还可以在此处阅读C#与Java事件的简短比较。首先,.Net中有一个标准的方法签名,通常用于事件。该语言允许将任何类型的方法签名用于事件,有些专家认为这种约定有缺陷(我基本上同意),但事实就是如此,我将在本例中遵循它。创建一个包含事件参数的类(派生自EventArgs)。公共类ComputerEventArgs:EventArgs{计算机计算机;//构造函数、属性等}在要触发事件的类上创建一个公共事件。类ComputerEventGenerator//我选择了一个可怕的名字顺便说一句。{公共事件EventHandlerComputerStarted;公共事件EventHandlerComputerStopped;公共事件EventHandlerComputerReset;...}调用事件。类ComputerEventGenerator{...privatevoidOnComputerStarted(计算机计算机){EventHandlertemp=ComputerStarted;如果(temp!=null)temp(这个,新的ComputerEventArgs(计算机));//如果事件是静态的,将“this”替换为null}}附加事件处理程序。voidOnLoad(){ComputerEventGeneratorcomputerEventGenerator=newComputerEventGenerator();computerEventGenerator.ComputerStarted+=newEventHandler(ComputerEventGenerator_ComputerStarted);}创建刚刚附加的处理程序(主要是通过在VS中按Tab键)。privatevoidComputerEventGenerator_ComputerStarted(objectsender,ComputerEventArgsargs){if(args.Computer.Name=="HAL9000")ShutItDownNow(args.Computer);完成后不要忘记分离处理程序。(忘记这样做是C#内存泄漏的最大来源!)}就是这样!编辑:老实说,我不明白为什么我的编号点都显示“1”。我讨厌电脑。有几种方法可以做你想做的事。最直接的方法是为托管类中的每个事件定义一个委托,例如公共委托无效ComputerStartedDelegate(计算机计算机);受保护的事件ComputerStartedDelegateComputerStarted;publicvoidOnComputerStarted(Computercomputer){if(ComputerStarted!=null){ComputerStarted.Invoke(computer);}}protectedvoidsomeMethod(){//...computer.Started=true;//或任何OnComputerStarted(computer);//...}任何对象都可以通过以下方式“侦听”此事件:Computercomp=newComputer();comp.ComputerStarted+=newComputerStartedDelegate(this.ComputerStartedHandler);protectedvoidComputerStartedHandler(Computercomputer){//dosomething}执行此操作的“推荐标准方法”是定义EventArgs的子类要保存计算机(以及旧/新状态和异常)值,将4个委托减少到1个。在在这种情况下,这将是一个更简洁的解决方案,特别是在未来扩展的情况下使用枚举来表示计算机状态。但基本技术仍然相同:使用-=语法而不是+=来删除侦听器在C#中,事件是委托。它们的行为类似于C/C++中的函数指针,但它们是派生自System.Delegate的实际类。在这种情况下,创建一个自定义EventArgs类来传递Computer对象。公共类ComputerEventArgs:EventArgs{私人计算机_computer;公共ComputerEventArgs(计算机计算机){_computer=计算机;}publicComputerComputer{get{return_computer;}}}然后公开生产者的事件:publicStventerpublicHartlerEventedProcuterpubliceventEventHandlerStopped;公共事件EventHandler重置;公共事件EventHandler错误;/*//调用Started事件*/privatevoidOnStarted(Computercomputer){if(Started!=null){Started(this,newComputerEventArgs(computer));}}//添加OnStopped、OnReset和OnError}事件的消费者然后将处理函数绑定到消费者上的每个事件。公共类ComputerEventConsumer{publicvoidComputerEventConsumer(ComputerEventProducerproducer){producer.Started+=newEventHandler(ComputerStarted);//添加其他事件处理程序}privatevoidComputerStarted(objectsender,ComputerEventArgse){}}当ComputerEventProducer调用OnStarted时,将调用Started事件,然后调用ComputerEventConsumer.ComputerStarted方法。委托声明一个函数签名,当它用作类的事件时,该函数签名也充当已注册调用目标的集合。+=和–=事件语法用于将目标添加到列表中。而以下委托用作事件://argumentsforeventspublicclassComputerEventArgs:EventArgs{publicComputerComputer{get;放;}}公共类ComputerErrorEventArgs:ComputerEventArgs{publicExceptionError{get;放;}}//事件委托的公共委托voidComputerEventHandler(objectsender,ComputerEventArgse);publicdelegatevoidComputerErrorEventHandler(objectsender,ComputerErrorEventArgse);//引发事件的组件publicclassThing{publiceventComputerEventHandlerStarted;公共事件ComputerEventHandler已停止;公共事件ComputerEventHandler重置;公共事件ComputerErrorEventHandler错误;您可以通过以下方式订阅这些事件:classProgram{staticvoidMain(string[]args){varthing=newThing();thing.Started+=thing_Started;}staticvoidthing_Started(objectsender,ComputerEventArgse){thrownewNotImplementedException();}}Objectsender和EventArgse是一个非常一致的约定,尽管参数可以是任何东西。+=thing_started将首先创建一个指向目标方法的委托实例,然后将其添加到事件中。在组件本身上,您通常会添加触发事件的方法:publicclassThing{publiceventComputerEventHandlerStarted;publicvoidOnStarted(Computercomputer){if(Started!=null)Started(this,newComputerEventArgs{Computer=computer});如果没有向事件添加代理,则必须测试null。当您进行方法调用时,将调用任何已添加的代理。这就是为什么对于事件,返回类型为void-没有单一的返回值-因此要反馈信息,您将在EventArgs上拥有事件处理程序将更改的属性。另一个改进是使用通用的EventHandler委托,而不是为每种类型的参数声明一个具体的委托。公共类事物{公共事件EventHandler开始;公共事件EventHandler已停止;公共事件EventHandler重置;公共事件EventHandler错误;非常感谢您的回答!终于,我开始明白是怎么回事了。就一件事;看来,如果每个事件都有不同数量/类型的参数,我需要创建一个不同的::EventArgs类来处理它:publicvoidcomputerStarted(Computercomputer);publicvoidcomputerStopped(计算机计算机);publicvoidcomputerReset(计算机计算机);publicvoidbreakPointHit(Computercomputer,intbreakpoint);publicvoidcomputerError(Computercomputer,Exception异常);这将需要三个阶段来处理事件!?(两个自定义,一个使用默认的EventArgs.Empty类)干杯!好的,最后的澄清!:这是我在代码中实现这些事件的最佳方式吗?以上就是C#学习教程:C#事件处理(对比Java)分享的全部内容。如果对大家有用,需要进一步了解C#学习教程,希望大家多加关注——publicclassComputer{publiceventEventHandlerStartedpubliceventEventHandlerStopped;公共事件EventHandler重置;公共事件EventHandlerBreakPointHit;公共事件EventHandler错误;publicComputer(){Started=delegate{};停止=委托{};重置=委托{};BreakPointHit=}delegate{Error=delegate{};}protectedvoidOnStarted(){Started(this,EventArgs.Empty);}protectedvoidOnStopped(){Stopped(this,EventArgs.Empty是);}protectedvoidOnReset(){Reset(this,EventArgs.Empty);}protectedvoidOnBreakPointHit(intbreakPoint){BreakPointHit(this,newBreakPointEvent(breakPoint));}protectedvoidOnError(System.Exceptionexception){Error(this,newExceptionEvent(exception));}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载请注明出处: