C# · 12月 30, 2021

在C#中升级

(我知道标题听起来很简单,但坚持 – 这可能不是你认为的问题.)

在VB.NET中,我能够编写自定义事件.例如,我有一个单独的线程会定期引发一个事件,在这种情况下,GUI需要更新.我不想忙线程打扰UI计算,我不想把Me.Invoke(Sub()…)放在事件处理程序中,因为它也是从GUI线程调用的.

我想出了这个非常有用的代码段. GUI线程将设置EventSyncInvoke = Me(主窗体).然后,线程可以像往常一样提升事件TestEvent,没有特殊的代码,并且可以在GUI线程上无缝执行:

Private TestEventDelegate As EventHandlerPublic EventSyncInvoke As System.ComponentModel.ISynchronizeInvokePublic Custom Event TestEvent As EventHandler AddHandler(value As EventHandler) TestEventDelegate = [Delegate].Combine(TestEventDelegate,value) End AddHandler RemoveHandler(value As EventHandler) TestEventDelegate = [Delegate].Remove(TestEventDelegate,value) End RemoveHandler RaiseEvent(sender As Object,e As System.EventArgs) If EventSyncInvoke IsNot Nothing Then EventSyncInvoke.Invoke(TestEventDelegate,{sender,e}) Else TestEventDelegate.Invoke({sender,e}) End If End RaiseEventEnd Event

现在在C#我可以做到这一点:

public event EventHandler TestEvent add { testEventDelegate = (EventHandler)Delegate.Combine(testEventDelegate,value); } remove { testEventDelegate = (EventHandler)Delegate.Remove(testEventDelegate,value); }}

但在哪里可以做定制养育?

编辑:
其他答案告诉我,我不能直接在C#中做到这一点,但不是为什么我不能,为什么我不想要的理由.我花了一段时间来了解C#事件如何与VB.NET进行比较.我离开了my own explanation,对于那些没有把握好的人,开始思考正确的路线.

老实说,我习惯了样板OnTestEvent格式,我不太喜欢使它与其他帮助方法不同的想法. :-)现在我明白了理由,我看到它实际上是放这个东西的最好的地方.

解决方法 VB.NET允许您隐藏使用RaiseEvent关键字调用代理的背景详细信息. RaiseEvent调用事件委托或自定义事件的RaiseEvent部分.

在C#中,没有RaiseEvent.举办活动基本上不仅仅是召集一个代表.当您正在做的所有提升它都是调用委托时,没有任何自定义的RaiseEvent部分可以被无缝地调用.所以对于C#,自定义事件就像骨架,实现添加和删除事件,但不能实现提升它们的能力.这就像将所有的RaiseEvent TestEvent(sender,e)替换为自定义RaiseEvent部分的代码.

对于正常的事件,提高大致类似于NormalEvent(sender,e).但是,一旦你放入一个自定义的添加和删除,你必须使用添加和删除中使用的任何变量,因为编译器不再这样做了.这就像VB.NET中的自动属性:一旦手动放入getter和setter,你必须声明并处理你自己的局部变量.所以代替TestEvent(sender,e),使用testEventDelegate(sender,e).那就是你重新路线的事件代表.

我比较了从VB.NET到C#的移动,不得不用您的自定义RaiseEvent代码替换每个RaiseEvent. RaiseEvent代码部分基本上是一个事件和一个帮助函数.实际上,在一个受保护的OnTestEvent方法中的VB.NET或C#中只有一个RaiseEvent的实例是标准的,并且调用该方法来引发事件.这允许任何具有访问受保护(或私有或公开)OnTestEvent的代码来引发事件.对于你想要做的,只要将其放在方法中更容易,更简单,执行得更好一点.这是最好的做法.

现在,如果你真的想要(或需要)以某种方式模仿VB.NET的RaiseEvent肮脏隐藏的调用SomeDelegate(sender,e)并且有魔法发生,你可以简单地隐藏第二个委托中的nitty-gritty:

NiceTestEvent =(sender,e)=> eventSyncInvoke.Invoke(testEventDelegate,new object [] {sender,e});

现在可以调用NiceTestEvent(sender,e).您将无法调用TestEvent(sender,e). TestEvent只适用于通过Visual Studio将告诉您的外部代码添加和删除.