Показать сообщение отдельно
Старый 30.10.2007, 11:18   #10  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
Читал о следующем

Цитата:
Вы можете пересчитывать ваши коллекции с помощью либо enumerator либо iterator. Когда классы коллекции были впервые представлены в Dynamics AX, iterator это была единственная опция. Но по причине hard-to-find ошибок, был добавлен enumerators, а iterators сохранился для дальнейшей совместимости. Для выявления этих различий, приведен следующий код для пересчета обоими способами.
X++:
List list = new List(Types::Integer);
ListIterator iterator;
ListEnumerator enumerator;
;
//Populate list.
...

//Traverse using an iterator.
iterator = new ListIterator(list);
while (iterator.more())
{
    print iterator.value();
    iterator.next();
}

//Traverse using an enumerator.
enumerator = list.getEnumerator();
while (enumerator.moveNext())
{
    print enumerator.current();
}
Первое отличие это путь, которым создаются сущности iterator и enumerator. Для iterator, вы вызываете new, а для enumerator, вы уже получаете сущности из класса коллекции вызовом метода getEnumerator. В большинстве случаев, обе реализации работают одинаково хорошо. Однако, когда класс коллекция передается на другой уровень (tier) с уровня на котором он пересчитывается, ситуация совершенно отличная. Например, если пересчет коллекции происходит на клиенте, а затем передается на сервер, iterator терпит крах, так как iterator не поддерживает cross-tier вызовов. Еnumerator не поддерживает cross-tier вызовов так же, но он и не должен, так как он инициируется на том же самом уровне (tier) что и класс коллекция. Пересчет на уровне сервера, используя уровень клиента, enumerator будет достаточно нагружать сеть, но результат будет логически корректным. Так как некоторый код отмечается как Called From, означающий, что он может выполняться на том уровне из которого вызван, вы можете испортить логику при использовании iterators, даже если вы тестируете по одному плану. В большинстве случаев, hard-to-track баги такие, как this surface происходят, когда операция выполняется в пакетной обработке.
Примечание

В предыдущих версиях Dynamics AX, эта проблема была более явной так как разработка и тестирование могло происходить в двух уровневой архитектуре, а эта проблема появляется только в трех уровневой архитектуре.

Второе отличие между iterators и enumerators это путь, по которому происходит сам пересчет. При использовании iterator, вы должны явно использовать вызов more и next; при использовании enumerator, метод moveNext обрабатывает это сам. Большинство разработчиков получали бесконечный цикл, просто потому что забывали дописать move a pointer. Это не существенная проблема, но иногда это раздражает во время разработки.
При постоянном использовании enumerator, вы не столкнетесь ни с одной из этих проблем. Единственная ситуация, в которой следует использовать iterator это удаление элементов из List collection. Следующий код показывает, как это реализовать.
X++:
List list = new List(Types::Integer);
ListIterator iterator;
;
list.addEnd(100);
list.addEnd(200);
list.addEnd(300);

iterator = new ListIterator(list);
while (iterator.more())
{
    if (iterator.value() == 200)
        iterator.delete();
    iterator.next();
}
print list.toString(); //{100, 300}
pause;
За это сообщение автора поблагодарили: Dudnik Anton (1).