AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX Blogs
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 26.09.2007, 23:51   #1  
Blog bot is offline
Blog bot
Участник
 
25,459 / 846 (79) +++++++
Регистрация: 28.10.2006
dax-dilettante: 15. System Classes \ The Collection Classes
Источник: http://dax-dilettante.blogspot.com/2...hapter155.html
==============

(последнее обновление: 10.08.07)
(основной перевод: 27.07.07 - 10.08.07)


Классы-коллекции

Библиотека классов в Dynamics AX содержит полезный набор классов-коллекций (collection classes). Класс-коллекция может содержать данные любого допустимого в X++ типа, включая объекты. Классы-коллекции - Set, List, Map, Array и Struct - иногда называют фундаментальными классами (foundation classes) или, как это было в предыдущих версиях программы, Axapta Foundation Classes (AFC).

Все классы-коллекции хранятся в памяти, поэтому при добавлении в них новых элементов следует помнить об увеличении размеров коллекции в памяти. Если же вам необходимо обрабатывать огромные объемы данных, то следует рассмотреть альтернативы, такие как временные таблицы или частично размещенные на диске массивы X++.

Доступ к элементам коллекции может быть получен путем последовательного перебора всей коллекции (traversing) или при помощи направленного поиска в ней (lookup). Чтобы решить, какие классы-коллекции использовать в конкретном случае, вы должны проанализировать ваши данные и подумать, как именно вы хотите получать доступ к элементам коллекции. В следующих разделах подробно рассматривается каждый из классов-коллекций.

Класс Set ("Множество", "Набор")

Объект Set представляет собой коллекцию, которая может содержать любое число отличающихся друг от друга (уникальных) значений любого имеющегося в X++ типа данных. Все значения в Set должны быть одного и того же типа. Попытка добавления в Set значения, которое уже там имеется, игнорируется и не приводит к увеличению количества элементов. Элементы в коллекции хранятся способом, облегчающим их поиск. В следующем примере демонстрируется создание объекта Set, состоящего из целочисленных значений, и последующее добавление в него значений 100, 200 и еще раз 100:
Set set = new Set(Types::Integer);
;
set.add(100);
set.add(200);
set.add(100);
print set.toString(); //{100, 200}
print set.elements(); //2
print set.in(100); //true
print set.in(150); //false
pause;
Set особенно полезно в ситуациях, когда вы хотите сортировать элементы, так как элементы в нем сортируются при вставке, либо когда вы хотите отслеживать объекты. Вот пример из класса AxInternalBase:

protected boolean isMethodExecuted(str _methodName, ...)
{
if (setMethodsCalled.in(_methodName))
return true;

setMethodsCalled.add(_methodName);
...
return false;
}
Объект setMethodsCalled отслеживает, какие методы были выполнены.

Как показано на рисунке 15-2, вы можете выполнять логические операции с ипользованием Set. Вы можете создать объединение (union) двух множеств, найти пересечение (intersection) между ними или найти отличие (difference) одного от другого.

Рисунок 15-2. Операции Set.


Логические операции можно проиллюстрировать следующим фрагментом кода:
Set set1 = new Set(Types::String);
Set set2 = new Set(Types::String);
;
set1.add('a');
set1.add('b');
set1.add('c');

set2.add('c');
set2.add('d');
set2.add('e');

print Set::union(set1, set2).toString(); //
{a, b, c, d, e}
print Set::intersection(set1, set2).toString(); // {c}
print Set::difference(set1, set2).toString(); //
{a, b}
print Set::difference(set2, set1).toString(); //
{d, e}
pause;
Класс List ("Список")

Объекты класса List представляют собой структуры, которые могут содержать любое количество элементов, доступ к которым осуществляется последовательно. List может содержать значения любого типа X++. Все значения в List должны соответствовать этому типу, указываемому при создании списка. Элементы могут быть добавлены на один из "краев" списка - либо в конец, либо в начало. List аналогичен Set, за исключением того, что List может содержать повторяющиеся значения, и порядок хранения элементов в списке определяется последовательностью операторов вставки значений в список. Следующий пример показывает добавление целых чисел в список (заметьте, что последнее число 300 вставляется в начало списка):
List list = new List(Types::Integer);
;
list.addEnd(100);
list.addEnd(200);
list.addEnd(100);
list.addStart(300);

print list.toString(); // 300, 100, 200, 100
print list.elements(); // 4
pause;
Класс Map ("Карта соответствия")

Объекты данного типа устанавливают соответствие между одним значением ("ключом") и некоторым другим значением ("значением"). Рисунок 15-3 иллюстрирует это:

Рисунок 15-3. Пример Map.


В качестве ключа (key) и значения (value) можно использовать данные любого типа, включая класс и запись. Ключ и значение не обязаны быть одного и того же типа. Возможность эффективного поиска в Map делает объекты этого класса полезными для кэширования информации.

Несколько разных ключей могут указывать одновременно на одно и то же значение, тогда как один ключ одновременно может относиться только к одному значению. Добавление пары "ключ-значение" в Map, где такой ключ уже имеется и связан с некоторым иным (старым) значением, фактически приводит к замене старого значения на новое.

В следующем примере показано, как заполнить Map ключами и значениями, приведенными на рисунке 15-3, а затем выполнить поиск:
Map map = new Map(Types::String, Types::Enum);
Word wordType;
;
map.insert("Car", Word::Noun);
map.insert("Bike", Word::Noun);
map.insert("Walk", Word::Verb);
map.insert("Nice", Word::Adjective);

print map.elements(); //4;

wordType = map.lookup("Car");
print strfmt("Car is a %1", wordType); //Car is a Noun
pause;
Map генерирует исключение, если метод lookup вызывается для поиска несуществующего ключа. Вы можете вызвать метод exists для проверки существования ключа перед вызовом lookup. Это особенно полезно в транзакциях, где вы не в состоянии элегантно перехватить исключение:
if (map.exists("Car"))
wordType = map.lookup("Car");
Класс Array ("Массив")

Объект Array может содержать элементы одного заданного типа данных, в том числе объекты и записи (в отличие от массивов, встроенных в язык X++). Значения хранятся последовательно. Массив может расширяться по мере необходимости, так что вам не нужно задавать его размер в момент инициализации. Как и для встроенных массивов X++, подсчет элементов в Array начинается с 1 (one-based indexing), а не с 0.
Array array = new Array(types::class);

array.value(1, new Point(1, 1));
array.value(2, new Point(10, 10));
array.value(4, new Point(20, 20));

print array.lastIndex(); //4
print array.value(2).toString(); //(10, 10)
pause;
Используемый в примере выше класс Point объявляется ниже - в примере раздела, посвященного сериализации.

Класс Struct ("Структура")

Объекты Struct могут содержать наборы значений любого типа X++. В Struct хранится информация о некоторой сущности. Например, вы можете хранить такую информацию о складской номенклатуре, как идентификатор, наименование и цену, и обращаться с этим комплексом информации как с "единым целым".

Объекты Struct позволяют хранить информацию подобно классам и таблицам. Вы можете представить себе Struct как облегченный класс. Объект Struct существует только в области видимости программного кода, в котором он обрабатывается - что не обеспечивает полиморфизма, присущего большинству классов, или "сохраняемости", присущей таблицам. Основные преимущества использования Struct заключаются в том, что вы можете динамически добавлять новые элементы и вам не требуется определять новый тип данных в AOT.

Как показано в нижеследующем примере, доступ к элементам Struct не сильно типизирован - вы ссылаетесь на объекты Struct, используя строковый литерал. Вам следует использовать Struct только в случае крайней необходимости. Ранее Struct уже была представлена в примере как класс-коллекция для обеспечения доступа к API таблицы свойств (property sheet), описанной в главе 3 "The MorphX Designers".

Вот пример использования Struct:
Struct item = new Struct("int Id; str Name");
;
item.value("Id", 1000);
item.value("Name", "Bike");

print item.toString(); //id=1000; Name="Bike"

item.add("Price", 299);
print item.toString(); //id=1000; Name="Bike"; Price=299
print item.fields(); //3
print item.fieldName(1); //Id
print item.fieldType(1); //int
print item.value("Id"); //1000
pause;
Производительность - интересная тема, связанная с использованием классов, таблиц и класса Struct. Предположим, вам нужен составной тип для хранения значений. Допустим, что этот составной тип - точка, характеризующаяся двумя вещественными значениями (координатами): x и y. Вы можете смоделировать эту точку тремя способами :

* Используя Struct с двумя полями, x и y.

* Определив новый класс, в котором конструктор принимает x и y как параметры, и используя два метода доступа к значениям координат.

* Определив таблицу с двумя полями, x и y. При этом вам не нужно будет вставлять записи в постоянную (или временную) таблицу; вы используете запись только для хранения точки в памяти.

Можно протестировать эти три способа, создав каждым из них 5000 точек, присвоив значения их координатам и добавив в общий набор (Set). Рисунок 15-4 показывает замечательный результат.

Рисунок 15-4. Эффективность объектов Struct, классов и таблиц как составных типов.


Два первых способа сопоставимы по скорости, но третий - в пять-семь раз быстрее. Разница в показателях объясняется издержками на инициализацию объектов и большим количеством вызовов методов. Эти издержки пренебрежимо малы в третьем случае.

Разница между Struct и классом является просто результатом различия в количестве вызовов методов. В случае Struct необходимо создать экземпляр Struct и вызвать метод value как для х, так и для y. В случае класса можно создать объект этого класса и присвоить значения с помощью конструктора, обойдясь одним вызовом метода. В случае таблицы можно задать значения полей непосредственно без единого вызова метода, а также без создания экземпляра объекта. Следующий код был использован для оценки результатов:<blockquote>//Struct implementation
for (i=1; i
__________________
Расскажите о новых и интересных блогах по Microsoft Dynamics, напишите личное сообщение администратору.
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как выполнять дефрагментирование RecID mazzy DAX: База знаний и проекты 174 05.10.2017 12:59
Передача функции в качестве параметра lemchey_white DAX: Программирование 20 21.01.2008 22:51
dax-dilettante: Для некоторых общих целей Blog bot DAX Blogs 11 27.09.2007 19:02
dax-dilettante: 15. System Classes \ The Global Session Classes Blog bot DAX Blogs 0 26.09.2007 23:51
dax-dilettante: 15. System Classes \ The Global Class Blog bot DAX Blogs 0 26.09.2007 23:51
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 17:18.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.