Navigation: Language Reference > 3 - Variable Declarations > Special Data Types >====== ANY (any simple data type) ====== | |
label ANY [,DIM( )] [,NAME( )] [,EXTERNAL] [,DLL] [,STATIC] [,THREAD] [,PRIVATE] [,PROTECTED]
ANY | A variable that may contain any value (numeric or string) or a reference to any simple data type. |
DIM | Dimension the variable as an array. |
NAME | Specify an alternate, “external” name for the field. |
EXTERNAL | Specify the variable is defined, and its memory is allocated, in an external library. Not valid within FILE, QUEUE, or GROUP declarations. |
DLL | Specify the variable is defined in a .DLL. This is required in addition to the EXTERNAL attribute. |
STATIC | Specify the variable's memory is permanently allocated. |
THREAD | Specify memory for the variable is allocated once for each execution thread. Also implicitly adds the STATIC attribute on Procedure Local data. |
PRIVATE | Specify the variable is not visible outside the module containing the CLASS methods. Valid only in a CLASS. |
PROTECTED | Specify the variable is not visible outside base CLASS and derived CLASS methods. Valid only in a CLASS. |
ANY declares a variable of a reference type which points to an internal RTL data structure. That structure can hold values of any numeric or string type, and references to any simple data type and to GROUPs. This allows an ANY variable to be used as a “generic” data type. An ANY variable may be declared within a CLASS, GROUP, or QUEUE structure, and may not be declared within a FILE structure.
If an ANY variable is declared outside a GROUP or QUEUE structure it is initialized to a NULL reference. Such ANY variables must be declared without the AUTO attribute.
When an ANY variable is the destination of a simple assignment statement (destination = source) and it contains a NULL reference, the RTL first creates an internal object of a default type and sets the ANY variable to referencethat object, and then performs the assignment of the value of the source expression to that internal object. When an ANY variable is the destination of a simple assignment statement and it contains a non-NULL reference, the assignment changes value of a variable, or a structure pointed ay by that reference.
When an ANY variable is the destination of a reference assignment statement (destination &= source), the RTL disposes its previous internal data and replaces it with a new object which holds a reference to the source variable. If the source of a reference assignment is NULL, the RTL disposes the previous internal data of the ANY variable from the left side, and then sets the ANY to a NULL reference.
When an ANY variable is the parameter of the CLEAR statement, the data it points to is cleared.
An ANY can be named in the USE attribute of any control in a window or report, provided that the ANY contains a non-NULL reference. If an ANY variable named in the USE attribute has not been set to reference to some variable declared in the program, i.e. it references a default object created by the RTL, the program should not perform a reference assignment with such ANY as a destination. (See the rules of reference variables as USE variables)
You cannot pass an ANY variable as a variable-parameter (by address) unless the calling procedure is prototyped to receive an untyped variable parameter (*?). If an ANY variable passed as a parameter of *? type has not been set to reference to some variable declared in the program, i.e. it references a default object created by the RTL, the program should not perform a reference assignment with such ANY as a destination, for example, from other threads, until the Procedure returns.
When an ANY variable is declared in a QUEUE structure, there are some special considerations that must be followed. This is due to the internal representation of an ANY and its polymorphic characteristics.
Use of CLEAR() and reference assignments with QUEUE entries.
Once an ANY variable in a QUEUE has been assigned a value, another simple assignment statement will assign a new value to the ANY. This means the previous value is replaced by the new value. If the first value has already been added to the QUEUE, then that entry will “point at” a value that no longer exists.
Once an ANY variable in a QUEUE has been reference assigned a variable (AnyVar &= SomeVariable), another reference assignment statement will assign a new variable to the ANY. This means the previous “pointer” is disposed of and replaced by the new “pointer.” If the first reference has already been added to the QUEUE, then that entry will “point at” a “pointer” that no longer exists.
Therefore, Queue fields of type ANY must be set to NULLs by executing the CLEAR statement with the QUEUE record structure itself as parameter, i.e. the program must execute CLEAR(Queue), before setting new values of queue field of type ANY for the next ADD() or PUT(). This is because CLEAR for QUEUEs and GROUPs are not applied recursively to the data pointed at from fields of reference types. Therefore, CLEAR(queue) just sets fields of type ANY to NULLs without disposing of their internal data.
In addition, you need to reference assign a NULL to all queue fields of type ANY (Queue.AnyField &= NULL), prior to deleting the QUEUE entry, in order to avoid memory leaks.
Example:
MyQueue QUEUE
AnyField ANY !Declare a variable to contain any value
Type STRING(1)
END
DueDate DATE !Declare a date field
CODE
MyQueue.AnyField = 'SoftVelocity'!Assign a string value
MyQueue.Type = 'S' !Flag data type
ADD(MyQueue)
CLEAR(MyQueue) !Clear the reference
MyQueue.AnyField &= DueDate !Assign a Reference to a DATE
MyQueue.Type = 'R' !Flag data type
ADD(MyQueue)
LOOP X# = RECORDS(MyQueue) TO 1 BY -1 !Process the QUEUE
GET(MyQueue,X#)
ASSERT(~ERRORCODE())
CASE MyQueue.Type
OF 'S'
DO StringRoutine
OF 'R'
DO ReferenceRoutine
END
MyQueue.AnyField &= NULL !Reference assign NULL before deleting
DELETE(MyQueue)
ASSERT(~ERRORCODE())
END
Use of ANY in CLASS/GROUP definitions.
If you do a reference assignment, or assign a value to an ANY that is a member of a CLASS or GROUP, you must clear the reference before destroying the class, otherwise the memory allocated by the reference assignment will not be freed.
Example:
AClass CLASS
AnyVar ANY,PRIVATE
AMethod PROCEDURE(FILE f)
Destruct PROCEDURE()
END
TextFile FILE,DRIVER('ASCII')
RECORD
Line STRING(255)
END
END
CODE
AClass.AMethod(TextFile)
AClass.AMethod PROCEDURE(FILE TextFile)
AGroup &GROUP
CODE
AGroup &= TextFile{PROP:Record}
SELF.AnyVar &= WHAT(AGroup, 1)
AClass.Destruct PROCEDURE()
CODE
SELF.AnyVar &= NULL !Without this line the program will leak memory
The ANY data type is represented with the special dedicated Clarion.ClaAny class.
The ANY data type of Clarion .NET is compatible with the ANY data type of the WIN 32 Clarion.
Remarks:
1. Unlike WIN32 Clarion, you can use the type ANY in a NEW statement.
2. You can't assign a reference to array to an ANY variable
See Also: