Итерирование Systems.Collections.List в Fujitsu COBOL
Как мне просмотреть коллекцию?
Я использую пробную версию компилятора Fujitsu/Alchemy и получаю медленную и слабую поддержку от поставщика.
Я в основном хочу передать List из C# в COBOL, а затем позволить COBOL использовать его и, возможно, обновить.
В C# обычным способом перебора коллекции является использование конструкции "foreach".
Однако конструкция C# "foreach" является сокращением для следующего:
private static void test1()
{
List<IDMSMapField> list1 = new List<IDMSMapField>();
int listSize = list1.Count;
// was just checking exact variablename and case here to copy into COBOL code.
int itemNumber = 0;
System.Collections.Generic.List<IDMSMapField>.Enumerator enumerator1 = list1.GetEnumerator();
while (enumerator1.MoveNext())
{
Console.Write("Okay" + enumerator1.Current);
}
}
Я могу написать это на языке COBOL, если вы поможете мне определить этот класс:
System.Collections.Generic.List<IDMSMapField>.Enumerator
Структура "Перечислитель" описана на сайте MSDN Microsoft.
Это говорит о том, что "перечислитель" - это структура, а не класс!
Из того, что я могу сказать в руководстве "Создание COBOLfromDotnetFrameworkDox.pdf", структуры определены как классы в репозитории COBOL.
Пример из руководства:
Define specifiers for structure in REPOSITORY, and any struct members:
CLASS STRUCT-name AS "struct-namespace"
PROPERTY PROP-struct-member AS "external-property-name"
Handle structures like classes. E.g. object to store a struct instance:
01 struct-object OBJECT REFERENCE STRUCT-name.
Ниже я повторяю некоторые варианты, которые я пробовал, которые не удалось скомпилировать из-за ошибки "невозможно решить". Если вы можете показать мне, как это правильно заявить, я думаю, мы можем двигаться вперед.
1.
REPOSITORY.
CLASS CLASS-LIST AS "System.Collections.Generic.List<>"
CLASS STRUCT-Enumerator AS "System.Collections.Generic.List<>.Enumerator"
.
Ошибка во второй строке:
ошибка JMN1795I-S: именованная ссылка 'System.Collections.Generic.List<>.Enumerator' не может быть разрешена.
Точно такая же ошибка для этого:
REPOSITORY. CLASS CLASS-LIST AS "System.Collections.Generic.List<>" CLASS STRUCT-Enumerator AS "System.Collections.Generic.List<T>.Enumerator" .
ошибка JMN1795I-S: именованная ссылка System.Collections.Generic.List.Enumerator не может быть разрешена.
Та же ошибка для этого:
СКЛАД. CLASS CLASS-LIST AS "System.Collections.Generic.List<>" Класс CLUC STRUCT-Enumerator как "System.Collections.Generic.List.Enumerator" .
ошибка JMN1795I-S: именованная ссылка System.Collections.Generic.List.Enumerator не может быть разрешена.
Другая альтернатива состоит в том, чтобы рассматривать это как массив, но я застрял на этом также.
REPOSITORY.
CLASS LIST-IDMSMapField AS "System.Collections.Generic.List<>[]"
CLASS CLASS-IDMSMapField AS "Lightyear.ERCB.IDMSDC.IDMSMapField"
CLASS CLASS-LIST-IDMSMapField EXPANDS LIST-IDMSMapField USING CLASS-IDMSMapField.
METHOD-ID. TW1DR4000-PF06 AS "TW1DR4000_PF06".
DATA DIVISION.
WORKING-STORAGE SECTION.
01 MapFieldItem USAGE OBJECT REFERENCE CLASS-IDMSMapField.
LINKAGE SECTION.
01 MapFieldList USAGE OBJECT REFERENCE CLASS-LIST-IDMSMapField.
PROCEDURE DIVISION...
...
SET MapFieldItem TO MapFieldList(1).
ошибка JMN2671I-S: ':' должно быть указано в модификаторе ссылки. ':' предполагается.
Я думаю, что компилятор видит (1) как операцию подстроки, возможно.
2 ответа
Это заняло некоторое время, но вот полный рабочий образец. Было несколько других приемов, чтобы добраться до свойств и переместить значения свойств, такие как Count, в переменную COBOL с соответствующим предложением USAGE. Ключевое слово "EXPANDS" (в хранилище) является еще одной ключевой частью решения.
В моей реальной программе я получу список в разделе LINKAGE, и у меня будет список более сложных объектов... но пример кода представляет собой более простой сценарий, который стоит отдельно и выполняется "как есть".
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
REPOSITORY.
CLASS List AS "System.Collections.Generic.List<>"
CLASS SysString AS "System.String"
CLASS SysBoolean AS "System.Boolean"
CLASS ListString EXPANDS List USING SysString
CLASS Enumerator AS "System.Collections.Generic.List<>+Enumerator"
CLASS StringEnumerator EXPANDS Enumerator USING SysString
PROPERTY PROP-Count AS "Count"
PROPERTY PROP-Current AS "Current"
.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 myList OBJECT REFERENCE ListString.
01 myEnum OBJECT REFERENCE StringEnumerator.
01 myBooleanEnumResult OBJECT REFERENCE SysBoolean.
01 myDotNetString OBJECT REFERENCE SysString.
01 myLoopCounter PIC 9(4) value zero.
01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO.
01 myCobolString PIC X(30) value spaces.
01 YN-END-LOOP PIC X value "N".
01 WS-ACCEPT-INPUT PIC X(80) value spaces.
PROCEDURE DIVISION.
1000-START.
INVOKE ListString "NEW" returning myList.
INVOKE myList "Add" using "Apples"
INVOKE myList "Add" using "Bananas"
INVOKE myList "Add" using "Orange"
SET myCobolCount to PROP-Count of myList
DISPLAY "Size of MyList = " myCobolCount
INVOKE myList "GetEnumerator" returning myEnum.
PERFORM UNTIL YN-END-LOOP = "Y"
INVOKE myEnum "MoveNext" returning myBooleanEnumResult
* How to test for Boolean, True = B'1' and False = B'0'
IF myBooleanEnumResult = B'0'
MOVE "Y" TO YN-END-LOOP
ELSE
SET myDotNetString TO PROP-Current of myEnum
ADD 1 TO myLoopCounter
SET myCobolString to myDotNetString
DISPLAY myLoopCounter " " myCobolString
END-IF
END-PERFORM
DISPLAY "END OF PROGRAM - PRESS ENTER TO END"
ACCEPT WS-ACCEPT-INPUT
.
END PROGRAM MAIN.
Используя.NET-реализацию Micro Focus, код может использовать расширение "выполнять перемены" для просмотра списка.
Итак, измененная версия:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
SPECIAL-NAMES.
REPOSITORY.
CLASS List AS "System.Collections.Generic.List"
CLASS SysString AS "System.String"
CLASS SysBoolean AS "System.Boolean"
CLASS ListString EXPANDS List USING SysString
PROPERTY PROP-Count AS "Count"
PROPERTY PROP-Current AS "Current"
.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 myList OBJECT REFERENCE ListString.
01 myLoopCounter PIC 9(4) value zero.
01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO.
01 myCobolString PIC X(30) value spaces.
01 WS-ACCEPT-INPUT PIC X(80) value spaces.
PROCEDURE DIVISION.
1000-START.
INVOKE ListString "NEW" returning myList.
INVOKE myList "Add" using "Apples"
INVOKE myList "Add" using "Bananas"
INVOKE myList "Add" using "Orange"
SET myCobolCount to PROP-Count of myList
DISPLAY "Size of MyList = " myCobolCount
move 0 to myLoopCounter
PERFORM varying myCobolString through myList
DISPLAY myLoopCounter " " myCobolString
ADD 1 to myLoopCounter
END-PERFORM
DISPLAY "END OF PROGRAM - PRESS ENTER TO END"
ACCEPT WS-ACCEPT-INPUT
.
END PROGRAM MAIN.
Далее, вместо использования синтаксиса репозитория и расширений, вы можете использовать встроенное объявление, например:
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN AS "COBOLEnumerationSample.Main".
WORKING-STORAGE SECTION.
01 myList type "System.Collections.Generic.List"[string].
01 myLoopCounter PIC 9(4) value zero.
01 myCobolCount PIC S9(9) COMP-5 VALUE ZERO.
01 myCobolString PIC X(30) value spaces.
01 WS-ACCEPT-INPUT PIC X(80) value spaces.
PROCEDURE DIVISION.
1000-START.
INVOKE type "System.Collections.Generic.List"[string]::"NEW"
returning myList
INVOKE myList "Add" using "Apples"
INVOKE myList "Add" using "Bananas"
INVOKE myList "Add" using "Orange"
SET myCobolCount TO myList::"Count"
DISPLAY "Size of MyList = " myCobolCount
MOVE 0 TO myLoopCounter
PERFORM varying myCobolString through myList
DISPLAY myLoopCounter " " myCobolString
ADD 1 TO myLoopCounter
END-PERFORM
DISPLAY "END OF PROGRAM - PRESS ENTER TO END"
ACCEPT WS-ACCEPT-INPUT
.
END PROGRAM MAIN.
В любом случае, мне просто нравится, что мы можем сделать это в COBOL, независимо от того, какой продукт используется.. Наслаждайтесь...