Итерация Systems.Collections.List в Fujitsu COBOL

Как перебрать коллекцию?

Я использую пробную версию компилятора Fujitsu/Alchemy и получаю медленную и плохую поддержку от поставщика.

В основном я хочу передать список из С# в 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

Структура "Перечислитель" задокументирована на сайте Microsoft MSDN.

В нем говорится, что "Перечислитель" - это структура, а не класс!

Из того, что я могу сказать в руководстве «Создание COBOL из DotnetFrameworkDox.pdf», структуры определяются как классы в COBOL REPOSITORY.

Пример из мануала:

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» не может быть разрешена.

  1. Точно такая же ошибка для этого:

        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» не может быть разрешена.

  1. Та же ошибка для этого:

    РЕПОЗИТОРИЙ. 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 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) как операцию подстроки.


person NealWalters    schedule 07.06.2011    source источник
comment
В ваших документах по Коболу где-нибудь говорится о вложенных типах?   -  person Henk Holterman    schedule 08.06.2011
comment
Было небольшое количество документации по Generics, но ничего не видел по вложенным типам (проверим завтра). У меня есть открытый инцидент поддержки с ними, но он двигался так медленно, что я подумал, может быть, поддержка сообщества может быть лучшим вариантом.   -  person NealWalters    schedule 08.06.2011
comment
Как насчет использования System.Collections.Generic.List`1[Lightyear.ERCB.IDMSDC.IDMSMapField]?   -  person user7116    schedule 08.06.2011
comment
Я нашел кое-что, синтаксис, которого я еще не видел: CLASS STRUCT-Enumerator as System.Collections.Generic.List‹›+Enumerator Вскоре попробую. Спасибо!   -  person NealWalters    schedule 08.06.2011
comment
Знак плюс перед Enumerator определенно является способом обработки вложенного класса, как предложил @Henk. У меня все еще есть другие глупые ошибки, я опубликую решение, когда заработаю на 100%.   -  person NealWalters    schedule 09.06.2011
comment
+1, COBOL в дикой природе. Прошло 10 лет с тех пор, как мне пришлось с ним работать.   -  person user7116    schedule 09.06.2011


Ответы (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.
person NealWalters    schedule 08.06.2011
comment
Я получаю следующую ошибку: JMN1750I-S REPOSITORY FILE OF CLASS 'SYSTEM.STRING' IS NOT ALLOCATED - person Rovann Linhalis; 31.07.2018
comment
Извините, я не использовал это программное обеспечение с 2011 года. - person NealWalters; 02.08.2018

Используя реализацию Micro Focus .NET, код может использовать расширение «выполнить изменение через» для просмотра списка.

Итак, измененная версия:

   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, независимо от того, какой продукт используется. Наслаждайтесь...

person Stephen Gennard    schedule 10.06.2011
comment
Спасибо за сравнение, но я пока в мире Fujitsu. - person NealWalters; 11.06.2011