.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.
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.)
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.
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:
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