== Containers ==
Containers are a basic form of linked lists. Container functions that you might need are '''conins''' , '''conpoke''' , '''conpeek''' , '''condel''' and '''connull'''.
One use of containers is to pass multiple variables between objects using a single call. This is particularly useful when considering 3-tier performance, as each call across a tier can be quite expensive. In that case, putting your variables into one container and passing that in a single call will gain some performance.
Another use is to eliminate some tedious coding practices when writing display methods for report labels. If you have to return values from tables just use a container to store them all then '''conpeek''' them out using a global incremental pointer. This pointer can be reset in the ''executeSection'' of your Design then use the same method for the DataMethod of your report label something like
display real showValue()
To declare a container simply prefix the container name with keyword '''container'''.
static void Job33(Args _args)
I found two methods of inserting data into a container, one is using '''conins'''(''container, start location, value1,...'') same syntax can be used for '''conpoke'''(''container, start location, value1,...''). Using '''conpoke''' will actually modify data at that location as opposed to inserting, the idea is that initially you can build your container with '''conpoke''' but if your container will need data added then use '''conins''' which will insert the data at specified location and bump the rest of the data.
static void Job33(Args _args)
//contest = conins(contest,1,"bla",3);
In the above I use '''conpoke''' to insert two values starting at location 1 into ''contest''. So after this our container will ... contain :) value "bla" at location 1 and value 3 at location 1. Data type for values is ''anytype''. '''conpeeek''' returns ''anytype'' data type.
== Performance considerations ==
One important detail about containers is the fact, that they are static structures. You cannot modify a container in-place, instead each addition or deletion has to iterate over the entire structure to copy all values into a newly allocated one. So every container manipulation has a runtime of O(n). Thus, whenever possible, read and write containers as a batch:
// writing a container
packedClass = [ version, var1, var2, var3 ];
// reading a container
[ version, var1, var2, var3 ] = packedClass;
I cannot tell how this is for reading operations, I suspect that they're O(1) much like arrays, but I wouldn't bet anything on it.
This whole thing is especially tricky in cases where you need variable-length containers which you usually create dynamically: This actually scales rather bad. However, there is a rather simple trick you can use if you run into this problem: The integrated List class does have a very nice packed format, which is just about what you need:
static container List2Container(List list)
result = list.pack();
switch (conpeek(result, 1))
return condel(result, 1, 3);
throw error(strfmt("The List version %1 is not suppported.", conpeek(result, 1)));
I had performance problems in this respect with containers having 50+ elements which have to be assembled dynamically (for various reasons not important here). Changing to a list and converting it into a container in a single batch is at least one magnitude faster there (no wonder, as appending to a list works in O(1) rather then O(n)).
|За это сообщение автора поблагодарили: alex55 (1).|
|axaptapedia: Tutorial Form MultiSelectCheckBox||Blog bot||DAX: База знаний и проекты||21||23.09.2010 14:16|
|gatesasbait: Quicksort on a container||Blog bot||DAX Blogs||1||16.12.2007 13:35|
|axcoder: AxPath is supported by axaptapedia||Blog bot||DAX Blogs||0||11.05.2007 10:00|
|Dynamics AX Geek: Storing objects in a container||Blog bot||DAX Blogs||0||28.10.2006 16:40|
|Опции темы||Поиск в этой теме|