Events
Events are a special kind of Member in a Class or Record that allow other parts of the code to subscribe to notifications about certain, well, events in the class.
An event is very similar to a Block type Field, but rather than just storing a single block reference, events are "multi-cast". This means they maintain a list of subscribers, and when calling the event, all subscribers will get a callback.
Platform Considerations
Although events are most commonly used on .NET and both Cocoa and Java have different paradigms to deal with similar concepts (such as regular Blocks, Delegate Classes (not to be confused with .NET's use of the term) and Anonymous Interfaces), events are supported on all platforms.
Event Declaration Syntax
A simple event declaration consists of the event
keyword, followed by a name for the event and the type of Block that can be used to subscribe to the event. The block type can be a named Alias, or an explicit block declaration:
event ButtonClick: EventHandler; // EventHandler is a named block defined elsewhere
event Status: block(aMessage: String);
Just as with Stored Properties, with this short syntax the compiler will take care of creating all the infrastructure for the event, including a private variable to store subscribers, and add
and remove
methods.
Optionally, an add
and remove
clause can be provided to explicitly name the methods responsible for adding and removing handlers. These methods must then be declared and implemented separately, and they must take a single parameter of the same type as the event (This, too, is comparable to the read
and write
statements for a Property). It is then up to the implementation of these methods to handle the subscription/unsubscription logic.
private
method AddCallback(v: EventHandler);
method RemoveCallback(v: EventHandler);
public
event Callback: EventHandler add AddCallback remove RemoveCallback;
Alternatively, on .NET only, a block field to be used for storage can be provided via the block
(or legacy delegate
) keyword:
private
fCallback: EventHandler;
public
event Callback: EventHandler block fCallback;
Subscribing to or Unsubscribing from Events
Externally, code can subscribe or unsubscribe from an event by adding or removing handlers. This is done with the special +=
and -=
operators, to emphasize that events are, by default, not a 1:1 mapping, but that each event can have an unlimited number of subscribers.
method ReactToSomething(aEventArgs: EventArgs);
//...
myObject.Callback += @ReactToSomething
//...
myObject.Callback -= @ReactToSomething
Of course, any compatible Block can be used to subscribe to an event – be it a method of the local type, as in the example above or e.g. an Anonymous Method.
Please refer to the Event Access Expression topic for more details.
Raising Events
An event can be raised by simply calling it like a Block or Method. Before doing so, one should ensure that at least one subscriber has been added, because firing a unassigned event, just as calling a nil
block, will cause a NullReferenceException.
The assigned()
System Function or comparison to nil
can be used to check if an event is assigned.
if assigned(Callback) then
Callback();
By default, only the type that defines the event can raise it, regardless of the visibility of the event itself. See more on this in the following section.
Visibility
The visibility of events is governed by the Visibility Section of the containing type the event is declared in, or the Visibility Modifiers applied to the event.
This visibility extends to the ability to add and remove subscribers, but not to the ability to raise (or fire off) the event, which can be controlled by the raise
statement, described below.
Optionally, separate visibility levels can be provided for the add
, remove
and raise
statements. These will override the general visibility of the event itself:
event Callback: EventHandler public add AddCallback private remove RemoveCallback;
Raise Statements
Optionally, a raise
statement combined with an (also optional) visibility level can be specified, in order to extend the reach of who can raise (or fire off) the event. By default, the ability to raise an event is private
, and limited to the class that declares it.
event Callback: EventHandler protected raise;
In the example above, raising the event (normally private) is propagated to a protected
action, meaning it is now available to descendant classes.
Static/Class Events
Like most type members, events are by default defined on the instance – that means the event can be called on and will execute in the context of an instance of the class. A event can be marked as static by prefixing the event declaration with the class
keyword, or by applying the static
Member Modifier:
class event SomethingChanged: EventHandler; // static event on the class itself
event SomethingElseChanged: EventHandler; static; // also static event on the class itself
Virtuality
The Virtuality of events can be controlled by applying one of the Virtuality Member Modifiers.
event SomethingChanged; virtual;
Events can be marked as abstract, if a descendant class must provide the implementation. Abstract events (and events in Interfaces may not define an add
, remove
or raise
statement.
event OnClick: EventHandler; abstract;
Other Modifiers
A number of other Member Modifiers can be applied to events.
deprecated
Makes an event deprecated.implements
ISomeInterface.SomeMember
(See Explicit Interface Implementations).locked
Like locked on, withself
as an expression.locked on
Expression
executes a lock on the expression around the accessors of this event.mapped to
(See Mapped Members).optional
(Interface members only).unsafe
Allows the use of unsafe types in event signatures.
See Also
- Event Access Expressions
- Block Types