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.
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
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
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
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
-= 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.
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.
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.
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
raise statements. These will override the general visibility of the event itself:
event Callback: EventHandler public add AddCallback private remove RemoveCallback;
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.
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
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
event OnClick: EventHandler; abstract;
A number of other Member Modifiers can be applied to events.
deprecatedMakes an event deprecated.
ISomeInterface.SomeMember(See Explicit Interface Implementations).
lockedLike locked on, with
selfas an expression.
Expressionexecutes a lock on the expression around the accessors of this event.
mapped to(See Mapped Members).
optional(Interface members only).
unsafeAllows the use of unsafe types in event signatures.
- Event Access Expressions
- Block Types