BEGINEXTENSION-ENDEXTENSION
|
|
|
|
NSupported in Synergy .NET
|
BEGINEXTENSION [type_param[, ...]] ([receiver,] type)member_def . . . ENDEXTENSION
Arguments
type_param
(optional) One or more type parameters for the extension block, separated by commas. It's only needed when type is an open generic that references it (e.g., @mygeneric<T>).
receiver
(optional) The identifier used inside the instance method or property to refer to the instance being extended. It's required if the block contains any instance members but can be omitted if the block contains only static members.
type
The type being extended. It can be a simple type (string), a closed generic (@IEnumerable<int>), or an open generic using the block's type parameter(s) (@mygeneric<T>). Reference types are prefixed with @.
member_def
The definition of a method, property, static member, or operator that will extend the class.
Discussion
BEGINEXTENSION and ENDEXTENSION mark the beginning and end of a block to declare extension members in a non-generic, static class. Extension blocks can define methods, properties, static members, and operators for an existing type without modifying the original type. These members can then be called as though they were instance or static members of the extended type.
Extension blocks must follow these rules:
-
The enclosing class must be static with no generic parameters.
-
Descriptor types (including non-CLS structures) can't be extended with this syntax. Instead, you must use the EXTENSION modifier in a METHOD statement.(Note that you can't use EXTENSION method syntax inside a BEGINEXTENSION-ENDEXTENSION block.)
-
A receiver name can't be reused as a param name or method type-param name; omitting the name restricts the block to static members only.
-
Duplicate signatures are not allowed.
-
Binary operators must be static. A unary operator must be declared with BYREF. A static unary operator can take explicit params.
-
Simple/auto properties are not supported.
-
Virtual, new, override, sealed, partial, protected, or abstract modifiers are not allowed.
-
BEGINEXTENSION-ENDEXTENSION blocks can't be nested.
-
Extension-level type generic type params can't be shadowed by method type params or method params.
-
Extending a closed generic (e.g., mygeneric<string>) doesn't apply to other instantiations (e.g., mygeneric<int>) or the open type.
-
Generic constraints on open-generic extension blocks are enforced when the method is called.
An extension member cannot override existing functionality. If an extension member has same signature as an existing member of the type being extended, the existing member has priority when the method call is resolved.
The example below declares an extension method:
public static class MyExtensions
beginextension (mcl, @myclass)
public method meth1, void
proc
console.writeline("meth1")
endmethod
endextension
endclass
Once declared, the extension method can be called as though it were an instance method of the extended type:
data cvar = new myclass(4) cvar.meth1() ;Instance-style extension method
The following example illustrates that an extension block can contain more than a single instance method. It can also declare static methods, instance properties, static properties, and operator overloads, all bound to the same extended type:
class myclass
public method myclass
parm1, int
proc
fld1 = parm1
end
public fld1, int
endclass
public static class MyExtensions
beginextension (mcl, @myclass)
public method meth1, void
proc
console.writeline("meth1")
endmethod
public static method smeth1, void
proc
console.writeline("smeth1")
endmethod
public property prop1, int
method get
proc
console.writeline("prop1")
mreturn mcl.fld1
endmethod
endproperty
public static property sprop1, int
method get
proc
console.writeline("sprop1")
mreturn 0
endmethod
endproperty
public static method op_Addition, int
parm1, @myclass
parm2, @myclass
proc
console.writeline("op_Addition")
mreturn parm1.fld1 + parm2.fld1
endmethod
endextension
endclass
Once declared, these members can be used just as they would be if myclass had defined them itself:
data cvar = new myclass(4) data cvar2 = new myclass(6) data ivar, int cvar.meth1() ;Instance method -> "meth1" MyExtensions.smeth1() ;Static method, called on the extension class -> "smeth1" ivar = cvar.prop1 ;Instance property -> "prop1", ivar = 4 ivar = MyExtensions.sprop1 ;Static property, called on the extension class -> "sprop1", ivar = 0 ivar = cvar + cvar2 ;Operator overload -> "op_Addition", ivar = 10
