是否等效于C#中VB的自定义RaiseEvent块? [英] Equivalent of VB's custom RaiseEvent blocks in C#?

查看:84
本文介绍了是否等效于C#中VB的自定义RaiseEvent块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我知道标题听起来很简单,但是请耐心等待-这可能不是您认为的问题.)

(I know the title sounds easy, but hold on—this probably isn't the question you think it is.)

在VB.NET中,我能够编写自定义事件.例如,我有一个单独的线程,该线程会定期引发一个事件,并且在该事件上,需要更新GUI.我不想让繁忙的线程烦扰UI计算,也不想将Me.Invoke(Sub()...)放在事件处理程序中,因为它也是从GUI线程调用的.

In VB.NET I was able to write custom events. For an example, I had a separate thread that would periodically raise an event and on that event the GUI would need to be updated. I didn't want the busy thread to bother with UI calculations and I didn't want to put Me.Invoke(Sub() ...) in the event handler since it was also called from the GUI thread.

我想出了这个非常有用的代码. GUI线程将设置EventSyncInvoke = Me(主要形式).然后线程可以像往常一样简单地引发事件TestEvent,而无需特殊代码,它将在GUI线程上无缝执行:

I came up with this very useful bit of code. The GUI thread would set EventSyncInvoke = Me (the main form). The thread could then simply raise the event TestEvent as usual, no special code, and it would be seamlessly executed on the GUI thread:

Private TestEventDelegate As EventHandler
Public EventSyncInvoke As System.ComponentModel.ISynchronizeInvoke

Public 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 RaiseEvent
End Event

现在在C#中,我可以做很多事情:

Now in C# I can do this much:

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


}

但是进行自定义筹集的能力在哪里?

But where is the ability to do custom raising?

推荐答案

其他答案告诉我,我无法直接在C#中执行此操作,但不是为什么不能执行此操作的理由以及为什么我不想我花了一些时间来了解与VB.NET相比C#事件如何工作.因此,这种解释是针对那些对此没有很好把握的人开始按照正确的思路进行思考的.

老实说,我非常习惯样板OnTestEvent格式,以至于我不喜欢将其与其他辅助方法不同的想法. :-)但是,现在我了解了基本原理,我发现它实际上是放置这些东西的最佳场所.

Honestly, I was so used to the boilerplate OnTestEvent format that I didn't quite like the idea of making it different from the rest of the helper methods. :-) But now that I understand the rationale, I see that it is actually the best place to put this stuff.

VB.NET允许您隐藏使用RaiseEvent关键字调用委托的背景详细信息. RaiseEvent调用事件委托或您的自定义RaiseEvent部分以获取自定义事件.

VB.NET allows you to hide the background details of calling the delegates with the RaiseEvent keyword. RaiseEvent calls either the event delegate or your custom RaiseEvent section for a custom event.

在C#中,没有RaiseEvent.基本而言,引发事件只是呼叫代表.当您要进行自定义的RaiseEvent部分调用时,都不能无缝调用它.因此,对于C#,自定义事件就像骨架一样,为事件实现添加和删除,但没有实现引发事件的能力.就像必须用自定义RaiseEvent部分中的代码替换所有RaiseEvent TestEvent(sender, e).

In C#, there is no RaiseEvent. Raising an event is basically no more than calling a delegate. No custom RaiseEvent sections can be seamlessly called when all you're doing to raise it is calling a delegate. So for C#, custom events are like skeletons, implementing add and remove for events but not implementing the ability to raise them. It's like having to replace all your RaiseEvent TestEvent(sender, e) with the code from the custom RaiseEvent section.

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

For a normal event, raising looks roughly like NormalEvent(sender, e). But as soon as you put in a custom add and remove, you must use whatever variable you used in the add and remove because the compiler isn't doing it anymore. It's like automatic properties in VB.NET: once you put in a getter and setter manually, you have to declare and handle your own local variable. So instead of TestEvent(sender, e), use testEventDelegate(sender, e). That's where you rerouted the event delegates.

我比较了从VB.NET到C#的情况,即必须用自定义的RaiseEvent代码替换每个RaiseEvents. RaiseEvent代码部分基本上是一个事件和一个辅助功能一起滚动.实际上,在VB.NET或C#中仅在受保护的OnTestEvent内只有一个RaiseEvent实例是一个标准.方法,然后调用该方法引发事件.这允许访问受保护的(或私有或公共的)OnTest E vent的任何代码引发该事件.对于您要执行的操作,只需将其放入方法中就可以变得更容易,更简单并且执行稍微更好.这是最佳做法.

I compared moving from VB.NET to C# with having to replace each of your RaiseEvents with your custom RaiseEvent code. A RaiseEvent code section is basically an event and a helper function rolled together. It's actually standard to only have one instance of a RaiseEvent in either VB.NET or C# inside a protected OnTestEvent method and call that method to raise the event. This allows any code with access to the protected (or private or public) OnTestEvent to raise the event. For what you want to do, just putting it in the method is easier, simpler and performs slightly better. This is best practice.

现在,如果您真的想(或需要)某种方式来模仿VB.NET的RaiseEvent隐藏细节调用SomeDelegate(sender, e)并发生魔术,您可以只需隐藏细节即可第二个代表中坚韧不拔:

Now if you really want to want (or need) somehow to mimic VB.NET's RaiseEvent nitty-gritty-hiding call SomeDelegate(sender, e) and have the magic happen, you can simply hide the nitty-gritty inside a second delegate:

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

现在您可以拨打NiceTestEvent(sender, e).但是,您将无法呼叫TestEvent(sender, e).正如Visual Studio会告诉您的那样,TestEvent仅用于外部代码的添加和删除.

Now you can call NiceTestEvent(sender, e). You won't be able to call TestEvent(sender, e) though. TestEvent is only for outside code to add and remove through, as Visual Studio will tell you.

这篇关于是否等效于C#中VB的自定义RaiseEvent块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆