First Chapter: Structured Data Types (II)
In the first part of this article we introduced Structured Data Types (SDT) and explained their creation. This second part provides a detailed description of their operation and collections management with SDTs. By GxOpen Task Force(*)
Before starting the main topic of this second chapter, we will explain how SDT work. Those of you who have worked with objects will understand the concept easily, but we will still provide a clear explanation for everyone.
When we declare a variable in our programs, we reserve a place in memory and when we assign it, the contents are copied from it to another place in memory corresponding to another variable or structure.
Example:
Variables:
&a of
"Numeric(5)" type
&b of "Numeric(5)"
type
Source:
&a =
1
&b = &a
&a = 2
msg(str(&a))
msg(str(&b))
The execution of this small code will display a message with value 2 and another with value1. It is very simple but you will see that working with SDT is quite different.
Let's see the following example using the "sdtCust" SDT defined in the previous chapter and described in detail at the end of this chapter:
Variables:
&Cus1
"sdtCust" type
&Cus2 "sdtCust".type
Source:
&Cus1.CusNam =
"Daniel"
&Cus2 = &Cus1
&Cus1.CusNam = "Marcelo"
msg(&Cus1.CusNam)
msg(&Cus2.CusNam)
Note that this example is very similar to the previous one but with the difference that this one will display "Marcelo" in the two messages.
At this point you must be wondering "how does it work?".
We have already mentioned that when assigning variables the memory contents are copied from one place to another but when we assign an SDT to another one, we are assigning a reference or pointer.
In the image below you can see that when defining the two variables (&Cus1 and &Cus2), a structure with all the SDT information is created somewhere in the memory, and the variable is assigned the memory address to this structure.

When assigning the variable &Cus1 to &Cus2, we are assigning the address to &Cus1 structure to &Cus2. See the graphic example below:

Hence, when a value is assigned to a &Cus1 attribute, it is also assigned to &Cus2 since it is a reference to the same structure.
This changes a little our perception of normal variables.
But, how can you copy only the contents of a SDT to another without assigning it the same address?:
Using the "Clone()" method. The clone method creates another structure in memory that is identical to and has the same data of the SDT that is being copied. See this example:
&Cus2 = &Cus1.Clone()
Therefore, we are working with different structures and when a value is assigned to a &Cus1 attribute, &Cus2 SDT content will not be affected.
SDT Collections Management
We are now ready to work with SDT collections.
This can be done in two ways:
1- Mark your SDT as a collection and define a name for your items.

2- Create a new SDT, e.g..: "Customers" and in the DataType column select "sdtCust". This is how WSDL Inspector obtains the structures to work with a specific WebService.

Because Nº1 is the most common way to work with SDT collections, we have used it in the examples below. Therefore, the SDT collection is "sdtCust" and each item will be "sdtCust.Cust".
Adding objects to a collection
In the following example we will load information from the customers table in a collection:
Variables:
&Cust of
"sdtCust.Cust" type
&Customers of "sdtCust"
type
Source:
for
each
&Cust.CusNam = CusNam
&Cust.CusSur = "Sent"
&Cust.CusDir = "18 de Julio 1830"
Customers.Add( &Cust.Clone() )
endfor
Note that we are using the "Clone()" method so as not to add the same reference each time an element is added to the collection, since we would always be working with the same element.
The code above may also be implemented in the following way without using the "Clone()" method.
for each
&Cust = new
sdtCust.Cust()
&Cust.CusNam =
CusNam
&Cust.CusSur = "Sent"
&Cust.CusAdd = "18 de Julio 1830"
Customers.Add( &Cust )
endfor
In this example we note the use of the "new" operand that creates a new structure in memory and assigns a new pointer to the SDT in order not to work with the same one that we added to the collection.
Scanning a collection and obtaining SDTs
Below you will see the different methods for scanning a collection and obtaining the SDTs contained in it. The following is the simplest procedure for scanning a SDT collection contents.
Variables:
&Cust of
"sdtCust.Cust" type
&Customers of "sdtCust"
type
Source:
Cust in
&Customers
msg(&Cust.CusNam)
endfor
Note that &Cust SDT is automatically loaded in each iteration and we can rapidly work with "&Cust" SDT
The other procedure is more traditional:
Variables:
&i of
"Numeric(5)" type
&Cust of "sdtCust.Cust"
type
&Customers of "sdtCust" type
Source:
i = 1 to
&Customers.Count
&Cust =
&Customers.Item(&i)
msg(&Cust.CusNam)
endfor
This is the classic procedure for scanning and obtaining SDTs. The possibility of using any other iteration structure is implied, as well as the possibility of obtaining SDTs directly through the index if there are elements in the collection using the "Count" property.
Removing SDT from a collection
The following code shows how to remove an element from a SDT collection.
Variables:
&i of
"Numeric(5)" type
&Customers of "sdtCust"
type
Source:
Customers.Count
0
&Customers.Remove(1)
endif
In the example, we check for elements in the SDT. If there are elements, the first element of the collection is removed.
Summing up, SDTs are a very powerful tool for GeneXus developers aimed at reducing code like most of the improvements in the subsequent versions. These examples show just the minimum amount of possibilities, but these objects allow performing actions ranging from exporting your data to XML to using small local databases managing collections and XML in your systems
GxOpen TaskForce team hopes these articles will be useful for the reader and looks forward to receiving your comments and suggestions on future topics to be developed.
GxOpen TaskForce
e-mail: info@gxopen.com