.NET has something that Java currently (as of JDK 7) lacks: Delegates. A delegate is like a C/C++ function pointer. C# and other .NET languages can use them for [Events] and passing references to functions around. ASIL uses the same concept and allows delegates to be used for the same types of activities. The biggest change from .NET's version is that ASIL supports two types of property delegates. .NET has no property delegates at all. ASIL also allows for delegates pointing to complex statements.
The table below shows what types of callable code that work with delegates:
Callable code type | Allowed? | Details |
---|---|---|
Operators | ✗ | |
Constructors | ✗ | Constructors are always called implicitly with the new keyword. |
Creators | ✗ | These are private and hidden to all code except that generated by the compiler. |
Destructors | ✗ | These are private and hidden to all code except the garbage collector. |
Commands | ✓ | The syntax must match exactly. |
Functions | ✓ | Again, the syntax must match exactly. The return type also has to mach. |
Complex Statements | ✓ | Not only does the syntax need to match exactly, but the instructions statement must also match. |
Properties | ✓ | First, the type must match—including usage of the const, ref, out, and byvalue keywords. Second, the delegate type must specify if the property should provide a get accessor, set accessor, or both. Listing neither specifies both. Function delegates can match some properties as long as they have a get accessor. Those properties can also match some functions. |
Property accessor | ✓ | The delegate type must specify if the delegate is for the set or get accessor. (The property doesn't have to provide the other.) This will NOT match ANY property—only accessors! |
Note: Delegates for some commands will match some Property set accessors. Similarly, some function delegates will match some Property get accessors. In both cases, the reverse is also true. This should be allowed and shouldn't be an error condition.
The delegate type is an instance of DelegateType which is derived from Type. Instances of a delegate are instances of DelegateInstance with a reference to the DelegateType and are derived from Object. Multiple derivation might be used on both to account for the various allowed types of delegate.
All types of delegate use the same syntax as the type of callable code they represent, except for complex statements (which get an extra clause) and the delegate keyword (all types). The code below has samples of each declaration. What would be the identifier for the procedure becomes the name of the delegate type. The code also creates a instance of the type. All delegate instances are reference types.
:::text
delegate command CommandDelegate var i%
var CommandDelegate MyCommandDelegateReference = null ' The value you're initializing the delegate instance to must either exist already or be null. You can't declare the procedure here!
delegate function FunctionDelegate
returns float
var FunctionDelegate MyFunctionDelegateReference = null
delegate statement StatementDelegate var ref String strParam
instructions String ' This is how you list the instruction list passed to the statement. Note the list is of types and not variable names.
var StatementDelegate MyStatementDelegateReference = null
delegate property double MainPropertyDelegate
get
set
var MainPropertyDelegate MyMainPropertyDelegateReference = null
delegate property double IndexedPropertyDelegate[int I] ' No accessors given so this requires both
var IndexedPropertyDelegate MyIndexedPropertyDelegateReference = null
delegate property double GetOnlyPropertyDelegate
get
var GetOnlyPropertyDelegate MyGetOnlyPropertyDelegateRefence = null
delegate property double GetAccessorPropertyDelegate.get ' Note the ".get" part
var GetAccessorPropertyDelegate MyGetAccessorPropertyDelegateReference = null
delegate property double SetAccessorPropertyDelegate.set
var SetAccessorPropertyDelegate MySetAccessorPropertyDelegateReference = null
In current versions of the C# language, the compiler implicitly replaces the name of a function with a delegate instance. ASIL though needs an extra step as it might look like you want to call the function. This is especially important when the procedure is a function or property returning a matching delegate. So ASIL makes use of the & operator like C/C++ did. Below are a series of assignments to the variables we declared in the sample above. (Note: the following code is valid DASIL, but not SASIL as SASIL doesn't allow executable code to live at the same level as procedure declarations.)
:::text
command MyComnand var int i ' A variable doesn't need to be declared the same way to match. So "int i" matches "i%".
' Have the command do something
MyCommandDelegateReference = &MyCommand
function MyFunction
returns float
' Have the function do something
MyFunctionDelegateReference = &MyFunction
statement MyStatement var out String strParam
var S$ = "sdfs"
instructions S$
MyStatementDelegateReference = &MyStatement
property double MyFullProperty
get
return 5.3
set
' store the value somewhere
MyMainPropertyDelegateReference = &MyFullProperty
MyGetAccessorPropertyDelegateReference = &MyFullProperty.get ' Note: the ".get" part cause this to match an accessor **delegate**
property double MyIndexedProperty[int i]
get
return someArray[i]
set
' do something with the passed value
MyIndexedPropertyDelegateReference = &MyIndexedProperty
As mentioned before, the following types of delegates can match each other:
One type | The type that might match | |
---|---|---|
Command | <==> | Property set accessor |
Function | <==> | Property get accessor (Even though callers can ignore the return value from a function, functions can NOT match property set accessors as those effectively return the ASIL equivalent of void, which functions in ASIL can't return.) |
Function taking no parameters | <==> | Non-indexed property that has a get accessor |
Function taking a single parameter that matches its return type | <==> | Non-indexed property that has both accessors |
Function taking parameters | <==> | Indexed property where the index parameters match the function parameters |
Function taking a single parameter that matches its return type plus other parameters | <==> | Indexed property where the index parameters match the extra function parameters |
Below is a sample of code that demonstrates some of these matches. This code also assumes the types declared above and is once more technically DASIL, not SASIL.
:::text
command PropMatchCommand var double dbl
' Do something here
MySetAccessorPropertyDelegateReference = &PropMatchCommand ' Valid
function PropMatchFunc
returns double
return 5.35
MyGetAccessorPropertyDelegateReference = &PropMatchFunc ' Valid
property int CommandMatch
set
' Do something with the value
MyCommandDelegateReference = &CommandMatch.set ' Valid
property float FuncMatch
get
return 3.65345
MyFunctionDelegateReference = &FuncMatch.get ' Valid
Once you have a non-null value inside a delegate reference, calling it is just like calling the actual procedure directly. The trick is making sure the reference is non-null. If you don't, a NullReferenceError (which doesn't need to be declared or caught) might be thrown. So you'd call MyCommandDelegateReference from above like this:
:::text
if MyCommandDelegateReference <> null then
MyCommandDelgateReference 5
Wiki: Events
Wiki: Functions
Wiki: Generics
Wiki: Home
Wiki: Keywords
Wiki: Properties
Wiki: keywords-delegate
Wiki: keywords-event
Wiki: keywords-function
Wiki: keywords-instructions
Wiki: operators-amp