A block type, also referred to as a delegate type on .NET, defines a method pointer that can be used to hold a reference to a Method or an Anonymous Method. Blocks are a safe way to dynamically invoke methods with a specific signature on unrelated classes.
Different from regular Function Pointers on native platforms (more on those below), block instance captures not only the implementation of the method in question, but also the Self pointer of the object instance that contains the method. This allows calls to blocks to execute in the context of a specific object instance, and access that object's members.
A block type is declared using the
block keyword, followed by a regular Method signature. This signature can include parameters and a result type.
type MyBlock1 = public block(aParameter: Integer); MyBlock2 = public block: String; MyBlock3 = public block;
In addition to
delegate keyword can also be used to declare a block.
The two keywords are interchangeable, and
delegate is mainly supported for backwards compatibility. We discourage the use of
delegate, because, while commonly used on .NET, the term can be confusing with what the terminology "delegate" refers to many other platforms, especially Cocoa. We recommend to use the
block keyword, exclusively.
Creating Block References
A block reference can be created by simply assigning a Method, Anonymous Method or Lambda Expression to a block variable.
To avoid ambiguity (e.g. as to whether to call the method and use its result, or assign the method itself), the method reference can be prefixed with the Address Of (
@) Operator. But note that this is seldomly required, except in cases of ambiguity (e.g. if the method itself returns a compatible block), ot to levarage type inference.
var x: MyBlock1 := @MyClass.MyMethod; // use a method as block var y: MyBlock2 := () -> "Hello"; // use a lambda as block var z := method begin // use an anonymous method DoSomething; end;
Invoking a Block
Invoking a block reference is as easy as calling into the block as if it were a regular local method:
x(15); var s: String := y(); z();
Note that different than in regular Method Calls, parenthesis are required to call the block. This is to avoid ambiguity between calling or referencing the block, e.g.:
var a := y; // assigns the same block as `y` to `a` var b := y(); // calls `y` and assigns the result to `a`.
Function Pointers are a type similar to blocks, but more limited. They can be declared using the same syntax, but with the
method keyword instead of
Different than blocks, function pointers do not capture a Self. As such, they can only refer to simple (global) functions, not to class methods. Anonymous methods or lambdas can be used as function pointers, as long as they do not access the surrounding scope or
Inline Block Types
Inline block types are blocks defined in a type reference, they use the same syntax as regular blocks, but without a name. On .NET and Java, these blocks must map to system-predefined generic delegates (
System.Func* on .NET and types in the Cooper Base Library for Java). Cocoa and Island support arbitrary inline blocks natively.
method DoSomething(aCallback: block(aStatus: String)); begin //... aCallBack("Done."); end;
The visibility of a block type can be controlled by applying a Visibility Modifier on the declaration. The default visibility is
Other modifiers do not apply to blocks.