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?
As others have said, each type of delegate is a type, just as if it were a regular class. So, in your example code, TestEventHandler
is a delegate type. A TestEventHandler
variable can reference any TestEventHandler
object, just like any other variable can reference any object of its own type. TestEventHandler
objects must be instantiated, just like objects of any other type.
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 MyMethodDelegate
type. That doesn't declare a variable of that type nor does it instantiate an object of that type.
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:
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 MyMethodDelegate
for 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 AddHandler
function.
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 AddressOf
function. So, for instance, when you do something like this:
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 AddHandler
and EventHandler
functions and events cannot be raised/invoked from outside of the class that defines it.