Думаю, многие знают, что такое Deep Assignment, или по нашему «глубокое присваивание»? Для тех, кто не в курсе — почитайте про это в Help`e.
Так вот, будет полезно знать некоторые особенности данной фичи, в применении к группам/классам/очередям/файлам.
1. Внутренняя реализация данной фичи основана на так называемом «списке соответствия полей», где каждому полю одной структуры сопоставлено поле с таким же названием из другой структуры. Используются, естественно, просто номера полей в своих структурах. Данный список составляется КОМПИЛЯТОРОМ во время компиляции программы. Таким образом данная фича НЕ РАБОТАЕТ для не типизированных реферал-указателей! Грубо говоря, разработчики просто поленились, так как данный список прекрасно строится на основе той инфы о группах, которая доступна в рантайме.
Пример:
TGrp GROUP,TYPE Field1 LONG END Grp1 LIKE(TGrp) Grp2 GROUP(TGrp) Field2 BYTE END GRef &GROUP ! Deep Assignment не работает GRef1 &Grp1 GRef2 &Grp2 Code GRef1 &= Grp1 GRef2 &= Grp2 GRef2 :=: GRef1 ! Будет работать GRef &= Grp1 GRef2 :=: GRef ! Работать уже не будет Return
Кстати! Для тех, кто не в курсе — не пытайтесь использовать реферал-указатели, пока они не указывают на какую-либо переменную! GPF обеспечен! Это, кстати, одна из ошибок в ядре, связанная с отсутствием проверок указателей на валидность.
2. Если первую особенность ошибкой не назовешь, то данная особенность, думаю, является именно ошибкой. И ошибкой компилятора! Как было сказано в п.1, «список соответствия полей» строится компилятором на основе имен полей, участвующих в «глубоком присваивании», структур. Но, при этом компилятор не учитывает, что поля с одинаковыми именами могут находится в разных подгруппах! Более того — что полей с одинаковыми именами в одной структуре может быть несколько в разных подгруппах! И компилятор честно начинает генерить пары соответствия для каждого совпадения имен полей!
Пример:
TDateTime GROUP,TYPE Date DATE Time TIME END Grp1 GROUP Create LIKE(TDateTime) ! 1,2,3 поля Change LIKE(TDateTime) ! 4,5,6 поля END Grp2 GROUP Create LIKE(TDateTime) Change LIKE(TDateTime) END Code Grp1 :=: Grp2 Return В результате, после такого присваивания, получим: Grp1.Create.Date = Grp2.Change.Date !!! Grp1.Create.Time = Grp2.Change.Time !!!
так как компилятор сгенерит для данного случая такой «список соответствия полей»:
1 - 1 ! Grp1.Create = Grp2.Create 2 - 2 ! Grp1.Create.Date = Grp2.Create.Date 2 - 5 ! Grp1.Create.Date = Grp2.Change.Date !!! 3 - 3 ! Grp1.Create.Time = Grp2.Create.Time 3 - 6 ! Grp1.Create.Time = Grp2.Change.Date !!! 4 - 4 ! Grp1.Change = Grp2.Change 5 - 2 ! Grp1.Change.Date = Grp2.Create.Date 5 - 5 ! Grp1.Change.Date = Grp2.Change.Date 6 - 3 ! Grp1.Change.Time = Grp2.Create.Time 6 - 6 ! Grp1.Change.Time = Grp2.Create.Time
Кстати! Вадим (Синявский), насколько я помню, в ранних релизах твоего шаблона DC использовалось именно Deеp Assignment?