Rules for passing one type to another
You can assign the following types interchangeably in an assignment statement. Implicit conversions are performed.
- a, asize
- i, i1, i2, i4, i8, byte, short, int, long, IntPtr, sbyte, ushort, uint, UIntPtr, ulong
- d, dsize, d., dsize.precision, decimal, double, float
- n, n.
- p, psize, p., psize.precision
- string
The string type has the same implicit conversions as the alpha type. Booleans can be assigned to or from any of the signed integer types.
You can pass the following types interchangeably as an argument to an IN parameter:
- a, asize, string
You can pass the following types interchangeably as an argument to an IN numeric parameter or a parameter without a specified direction:
- i, i1, i2, i4, i8
- d, d.
Int arguments can only be passed to int, n, or n.
The default passing convention is ^DESCR in traditional Synergy or BYVAL in Synergy .NET. When using BYREF in Synergy .NET, types must match exactly for the following types:
- byte, short, int, long, IntPtr, sbyte, ushort, uint, UIntPtr, ulong
- dsize, dsize.precision, decimal, double, float
- n, n.
- p, psize, p., psize.precision
If the parameter has a MISMATCH modifier, you can pass the following:
- an a type to an n type
- a d or d. type to an a type for subroutines and functions
You can also pass an a type to an OUT or INOUT non-CLS structure.
You can assign the following types to the listed Synergy object type in an assignment statement or as the value of an IN parameter:
Passing One Type to Another |
|
---|---|
Destination type |
Source type |
sbyte, i2 |
i1 |
short, i4 |
i2 |
int, i8 |
i4 |
long, d |
i8 |
decimal, d. |
d |
n, n. |
d |
i1, short |
sbyte |
i2, int |
short |
i4, long |
int |
ushort |
byte |
uint |
ushort |
ulong |
uint |
decimal |
ulong |
double |
float |
decimal |
double |
d., n, n. |
decimal |
@class |
An instance of class, or a derived class, or the cast of a class that has an explicit operator to convert to the destination type (see Conversion operators for more information) |
@* |
Any class instance, any interface (Synergy .NET only), or any boxed value type |
@interface |
The same interface, or a cast of another interface or class variable to this interface (Synergy .NET only) |
@delegate |
An instance of the same delegate, or a cast of a System.Object variable or method to this delegate (Synergy .NET only) |
structure |
Only the specified structure |
enumeration |
The same enumeration, one of the enumeration values, or a cast of another enumeration type or integer to this enumeration |
You can cast an object variable to a specific type to perform an explicit conversion between the types. (See Conversion operators for user-defined explicit conversions for classes.) For example,
record obj1, @class1 obj2, @class2 proc obj1 = new class1() obj2 = (class2)obj1 ;Invokes an op_Explicit that takes @class1 ; and returns @class2
For non-object code, the difference between casting and converting is that while casting simply looks at the data as if it were a certain type without modifying its contents, converting changes the content to an appropriate representation of the semantic value of the original for the new type. For example, ^A (or %A) performs a cast to alpha type, while %STRING converts to alpha. Passing a value into an argument that is declared as alpha performs an implicit cast to alpha; assigning a value to an alpha variable invokes an implicit conversion to alpha.
Here’s a non-object example:
record alpha, a1, "A" num, i1 proc num = ^i(alpha) ;num now contains 65 end
We strongly recommend that you don’t cast the result of an expression because you cannot rely on the size or precision of the result. Use the conversion functions instead (%DECML, %IMPLIED, %INTEGER, %STRING, or %ZONED). |
If you name a class record or a routine record, you can use that name to reference all the fields as one record for use in ISAM routines as one contiguous block of memory whose size is based on the sum of the declared fields’ sizes.
Passing different types of argument qualifiers
The table below compares how different types of argument qualifiers are passed in C#, traditional Synergy, and Synergy .NET.
|
C# |
Traditional Synergy |
Synergy .NET |
---|---|---|---|
Method parameter |
Unspecified means BYVAL |
Unspecified means IN |
Unspecified means IN BYVAL |
Subroutine/ |
N/A |
Unspecified means INOUT but literals can be passed; called routine to test if literal before writing |
Unspecified means INOUT but literals can be passed; called routine to test if literal before writing |
BYVAL (C# unspecified) |
A copy of the variable is passed and can be locally modified in the called routine. The contents of a BYVAL object can be modified, affecting the contents of the passed object unless an assignment is performed on the BYVAL parameter first |
N/A |
BYVAL means read (IN) only. INOUT can be added to get identical behavior to C# |
BYREF (C# REF/OUT) |
Implied READ/WRITE, the object handle or value type can be updated in the calling routine |
N/A |
Implied READ/WRITE, the object handle or value type can be replaced |
IN |
Local copy allowed to be modified |
Contents of object can be modified, parameters are immutable |
IN BYVAL, contents of object can be modified, parameters are immutable |
BYVAL CLS structure |
Local changes modify the copy passed |
N/A |
Local changes modify the copy passed |
Synergy structure |
N/A |
Local changes affect the caller's data unless marked IN |
Local changes affect the caller’s data unless marked IN |
Unprototyped routine |
N/A |
No compiler checking for literals passed to OUT or INOUT parameters. Warnings for objects passed to a routine |
N/A |
^VAL |
IntPtr |
Native int based on the platform on which it’s run |
Native int based on the platform on which it’s run |
The types a, d, and i are Synergex descriptor types. When passed as arguments, the descriptors themselves are immutable. Only the contents can change (for example, the alpha value is modified based on OUT or INOUT rules).
The following sample demonstrates the above behavior in Synergy.
cls structure mys ;.NET structure (CLS ignored in traditional) vars, int endstructure structure myss ;Synergy structure vars, int endstructure namespace will public class jeff public var1, int endclass endnamespace main record fred, @will.jeff myf, mys myfs, myss ab, a10 newint, int proc open(15,o,'tt:') fred = new will.jeff() xcall frank(fred, myf, myfs, ab, 1, newint) ;Note myf passed as ; value type writes(15,%string(fred.var1)) ; Should be 2 writes(15,%string(myf.vars)) ; Should be 0 writes(15,%string(myfs.vars)) ; Should be 2 writes(15,ab) ; Should be abcr end subroutine frank in fred, @will.jeff in joe, mys .ifndef dblnet jim, myss var, a10 .else byval jim, myss byval var, a10 .endc myi, int in newint, int proc jim.vars = 2 .ifdef DBLNET joe.vars = 2 ;Modified local copy of CLS struct mys .endc fred.var1 = 2 ;Can update contents of handle ; fred = new will.jeff() ;Cannot create new handle var = "abcr" .ifdef dblnet myi = 10 ;Allowed as unspecified, will get ; WRTLIT error in traditional .endc xreturn