vb.net EventHandler 和 Delegate 的误解

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15073327/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 12:31:09  来源:igfitidea点击:

EventHandler and Delegate misunderstanding

vb.netdelegates

提问by w0051977

Please take a look at the code below, which works as I would expect:

请看下面的代码,它按我的预期工作:

Partial Class _Default
    Inherits System.Web.UI.Page


    Delegate Sub TestEventHandler(ByVal o As Object, ByVal e As EventArgs)
    Dim alhandler As TestEventHandler = AddressOf TestEventMethod
    Public Event Test1 As TestEventHandler
    Public Event Test2 As TestEventHandler

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        AddHandler Me.Test1, alhandler
        AddHandler Me.Test2, alhandler
        RaiseEvent Test1(Me, e)
        RaiseEvent Test2(Me, e)
        RemoveHandler Me.Test1, alhandler
        RaiseEvent Test1(Me, e)
    End Sub

    Public Sub TestEventMethod(ByVal o As Object, ByVal e As EventArgs)
        MsgBox("Test")
    End Sub


End Class

I am confused with the two statements below:

我对以下两个陈述感到困惑:

Dim alhandler As TestEventHandler = AddressOf TestEventMethod '1
Public Event Test1 As TestEventHandler '2

1) This is saying that the reference of alHandler is a delegate that points to the address of a function. 2) This is saying that Test1 is an event of type Delegate. How can an event and a handler be a delegate?

1)这是说alHandler的引用是一个指向函数地址的委托。2) 这是说Test1 是Delegate 类型的事件。事件和处理程序如何成为委托?

回答by Steven Doggart

As others have said, each type of delegate is a type, just as if it were a regular class. So, in your example code, TestEventHandleris a delegate type. A TestEventHandlervariable can reference any TestEventHandlerobject, just like any other variable can reference any object of its own type. TestEventHandlerobjects must be instantiated, just like objects of any other type.

正如其他人所说,每种类型的委托都是一种类型,就好像它是一个常规类一样。因此,在您的示例代码中,TestEventHandler是委托类型。一个TestEventHandler变量可以引用任何TestEventHandler对象,就像任何其他变量可以引用它自己类型的任何对象一样。 TestEventHandler对象必须被实例化,就像任何其他类型的对象一样。

Delegates are special, however, in that you declare them using a different, special, syntax. For instance, if you had the following method:

然而,委托是特殊的,因为您使用不同的特殊语法声明它们。例如,如果您有以下方法:

Public Sub MyMethod(Text As String)
    ' ...
End Sub

You could create a delegate that matches that method signature like this:

您可以创建一个与该方法签名匹配的委托,如下所示:

Public Delegate Sub MyMethodDelegate(Text As String)

Remember, by doing so, that simply defines the MyMethodDelegatetype. That doesn't declare a variable of that type nor does it instantiate an object of that type.

请记住,这样做只是定义了MyMethodDelegate类型。这不会声明该类型的变量,也不会实例化该类型的对象。

There are two things in VB.NET syntax, however, which often cause a lot of confusion. First, when you declare an event, you can use two different syntax:

然而,在 VB.NET 语法中有两件事经常引起很多混乱。首先,当你声明一个事件时,你可以使用两种不同的语法:

Public Event MyEvent As MyMethodDelegate
Public Event MyEvent(Text As String)

Both of those lines do the same thing. The first line defines the event using an already defined delegate type. The second line essentially defines a new unnamed delegate on the fly and then uses it as the type for the event. (Note, I'm using the MyMethodDelegatefor simplicity, and that will work, but standards dictate that events should have a sender and an event args.)When an event is declared, think of it like a variable. Behind the scenes, it's really like a collection object that keeps a list of all the delegate objects that are added to it using the AddHandlerfunction.

这两行都做同样的事情。第一行使用已定义的委托类型定义事件。第二行本质上定义了一个新的未命名委托,然后将其用作事件的类型。 (注意,MyMethodDelegate为了简单起见,我使用的是 ,这会起作用,但标准规定事件应该有一个发送者和一个事件参数。)当一个事件被声明时,把它想象成一个变量。在幕后,它真的就像一个集合对象,它保存了使用该AddHandler函数添加到它的所有委托对象的列表。

The second confusing thing in VB.NET is that the compiler will automatically instantiate a new delegate object for you, if necessary, when you use the AddressOffunction. So, for instance, when you do something like this:

VB.NET 中的第二个令人困惑的事情是,如果需要,当您使用该AddressOf函数时,编译器会自动为您实例化一个新的委托对象。因此,例如,当您执行以下操作时:

AddHandler myObject.MyEvent, AddressOf MyMethod

It's just a shortcut for typing the full text, like this:

这只是输入全文的快捷方式,如下所示:

AddHandler myObject.MyEvent, New MyMethodDelegate(AddressOf MyMethod)

The latter, in my opinion is much more clear. What you are actually doing is creating a new object of that delegate type and pointing that delegate object to that method, and then adding that delegate object to the event (that event collection-like variable defined by the object's type).

后者,在我看来要清楚得多。您实际要做的是创建该委托类型的新对象并将该委托对象指向该方法,然后将该委托对象添加到事件(由对象类型定义的类似事件集合的变量)。

So, in your example, this line:

所以,在你的例子中,这一行:

Dim alhandler As TestEventHandler = AddressOf TestEventMethod

Would be more clearly written as:

会更清楚地写成:

Dim alhandler As TestEventHandler = New TestEventHandler(AddressOf TestEventMethod)

It's declaring a delegate variable and then setting it to a new delegate object that points to that particular method. In this case, it's just a standard delegate variable, not an event. Events are very similar to delegates field/properties. Events are essentially an accessor wrapper around a private delegate field, in the same way that properties often wrap a private field. The big differences between delegate fields and events are that events support the AddHandlerand EventHandlerfunctions and events cannot be raised/invoked from outside of the class that defines it.

它声明了一个委托变量,然后将其设置为指向该特定方法的新委托对象。在这种情况下,它只是一个标准的委托变量,而不是一个事件。事件与委托字段/属性非常相似。事件本质上是私有委托字段的访问器包装器,就像属性通常包装私有字段一样。委托字段和事件之间的最大区别在于,事件支持AddHandlerEventHandler函数,并且事件不能从定义它的类的外部引发/调用。