[ Previous ]
[ Index ]
[ Next ]
There are some confusing, but generally quite minor differences, between how events are declared, raised, and handled in VB.NET versus C#. Events are a simple concept and were painless to implement in VB 6.0. All of the message wiring was handled for you behind the scenes. Luckily, we can thank Microsoft for saving our naive minds from certain death by boredom by introducing delegates.
Seriously though, delegates are not very complicated, and in any case, you don't have any choice in using them if you want to make your code more eventful. A delegate is a type-safe function pointer. Once you have one you can point it to any method that matches the delegate's method signature and return type. Then, any call on the delegate, which is just a pointer to a function with the same signature, passes through to the method that it points to.
It's easy to see how .NET implements events. A collection of delegates is kept internally and, when an event is raised, each delegate is called (i.e. delegated to) in round-robin fashion. This is simply an implementation of the Observer design pattern (see Design Patterns by Gamma et. al.).
Visual Basic .NET thinly hides the use of delegates from you. The syntax for declaring one is the same as it was in VB 6.0:
Public Event TotalUpdatedEvent(ByVal Amount As Decimal)
It's not so transparent in C#. You first must define a delegate and then declare an event of that delegate type:
public delegate void totalUpdatedEventHandler(decimal amount);
public event totalUpdatedEventHandler totalUpdatedEvent;
There's one more important difference. Notice the void in the C# code above.
Event handlers for this particular event cannot return a value; however, it is
possible for handlers in C# to return values. This is not allowed in VB.NET where
all handlers must be Subs. Instead, in VB.NET events can pass ByRef parameters.
A Cancel
argument on a Closing event is a common example.
The differences between VB.NET and C# for raising events are rather uneventful:
RaiseEvent TotalUpdatedEvent(123.45)
versus the following in C#:
totalUpdatedEvent(123.45);
There are two ways to implement event handlers in VB.NET. The most common method
is to define a handler at design time with the Handles keyword. The object instance
raising the event must be declared with the WithEvents keyword, a carryover from VB 6.0 as shown below:
Module modMain
Private WithEvents calculator As calculator = New calculator()
Public Sub Main()
Call calculator.DoSomethingEventful()
End Sub
Private Sub TotalUpdated(ByVal Amount As Decimal) Handles calculator.TotalUpdatedEvent
Trace.Write("Total was updated to " + Amount.ToString())
End Sub
End Module
Public Class Calculator
Public Event TotalUpdatedEvent(ByVal Amount As Decimal)
Public Sub DoSomethingEventful()
RaiseEvent TotalUpdatedEvent(123.45)
End Sub
End Class
The second method is to associate a handler function with an event at run time by
using AddHandler together with AddressOf like so:
Module modMain
Private WithEvents calculator As calculator = New calculator()
Public Sub Main()
AddHandler calculator.TotalUpdatedEvent, AddressOf TotalUpdated
Call calculator.DoSomethingEventful()
End Sub
Private Sub TotalUpdated(ByVal Amount As Decimal)
Trace.Write("Total was updated to " + Amount.ToString())
End Sub
End Module
In C# all handlers must be associated at run time. This example demonstrates the handling of events in C#:
public class EventReceiver
{
static void Main(string[] args)
{
EventReceiver demo = new EventReceiver();
demo.doDemo();
}
public void doDemo()
{
Calculator calculator = new Calculator();
Calculator.totalUpdatedEventHandler handler = new Calculator.totalUpdatedEventHandler (OnTotalUpdated);
calculator.totalUpdatedEvent += handler;
calculator.doSomethingEventful();
}
public void OnTotalUpdated(decimal amount)
{
Trace.Write("Total was updated to " + amount.ToString());
}
}
internal class Calculator
{
public delegate void totalUpdatedEventHandler(decimal amount);
public event totalUpdatedEventHandler totalUpdatedEvent;
public void doSomethingEventful()
{
totalUpdatedEvent(123.45M);
}
}
Here are a few more things you should know about events:
- Handlers can be removed at run time with RemoveHandler and the -= operator.
- Handlers are executed in the order they were associated.
- When multiple handlers are associated with a single event in C# and the handler signature has a return type, then the value returned by the last handler executed will be the one returned to the event raiser.
- Visual Basic .NET provides default delegate types for you. But wait! Microsoft's endless generosity doesn't stop there. Default delegates are also provided for the events of the .NET Framework's controls and classes. Therefore, you only need to worry about delegates when you're defining your own events in C#.
[ Previous ]
[ Index ]
[ Next ]
All images and text on this site are licensed only for viewing on your
computer during your visit. No rights to save, copy, print,
redistribute, use in derivative works, or in
any other manner are allowed
or implied without the prior written consent of the author.
All images and text are ©Terry Smith unless otherwise noted. All rights reserved.
terry@terrysmith.net