You are eager to implement complex business rules in your programs, right? As you know, simple programming statements hold even complex programming logic together. This is true regardless of the programming language and regardless of the platform. Therefore, this chapter will address the following questions:
How do you go about implementing the various programming elements in .NET?
To what extent can you leverage your current COBOL programming skills?
Does .NET change some of the basics of COBOL syntax?
Certainly , you've implemented conditional and looping logic many times before. Practically every program you've written has contained variable declarations ”some of them even containing constants. But now you're dealing with .NET and it's time to see what's changed and what's stayed the same when it comes to the common programming syntax. I use the following areas to organize this discussion:
Defining data items
Coding logic statements
Noting observations
Using the VS .NET Solution Explorer
![]() |
Trying to see the technical world through the eyes of another is an interesting challenge. Trying to develop a guide (such as this book) that is useful for a cross- section of the mainframe community is no less of a challenge. This is one book, yet the mainframe community certainly is made up of more than just one type of mainframe programmer. Yes, we are a diverse group . So, I have to request a couple of things from you (if you don't mind).
To begin with, please keep in mind the objective of this book: to assist all (or as many as possible) of our mainframe brothers and sisters who are looking at .NET as a vehicle for a "technology transition" (remember, the reformation ). Next , keep in mind that some of us have never programmed outside of the 3270-Rumba- mainframe-JCL-VSAM-type environment.
Please be conscious of the fact that not everyone reading this book has experience creating mainframe applications on the Win32 platform, compiled using a Windows -based tool and uploaded to run on the host. Some among us have not developed COBOL applications using a Win32 tool and then executed modules on the Windows platform. Finally, not all of us "mainframers" have had the pleasure of coding in object-oriented COBOL.
I am reminding myself of these facts as well. Although my goal is to provide value in each chapter for every reader, I realize that some chapters will be of more interest to you than others will. You may prefer to simply skim this section (or others). However, skipping entire sections may yield unpredictable results. Therefore, I do not recommend taking that approach.
![]() |
On the mainframe, when you coded COBOL logic, you declared variables , structures, literals, and constants in your program. You were able to do this in your COBOL program's File Section, Working-Storage Section, or Linkage Section. You used the COBOL PICTURE clause to identify the type of data that you planned to store in the field.
For perspective, let's continue. To complete your mainframe COBOL field definition scenario, you simply used one of three characters (in your PICTURE clause) to identify the type of data: either "A," "X," or "9" for alphabetic, alphanumeric , or numeric, respectively. When you planned to perform calculations with your numeric data or had a subscript (index) in the Working-Storage Section, you were advised to add the USAGE clause. Once you had the USAGE clause in your code, you would typically choose between COMP and COMP-3 (COMP was the abbreviation for COMPUTATIONAL) depending on your need.
To complete your mainframe COBOL field definitions, you chose whether or not to add implicit or explicit decimals or other printable characters in your PICTURE clause. Then, after explicitly specifying the exact length of your field, you decided whether or not to add a VALUE clause. The VALUE clause was useful for assigning an initial value to your new field.
Well, guess what? With one caveat, practically all of your prior mainframe knowledge (when it comes to basic COBOL syntax) is transferable to the .NET platform.
The caveat? You will only use this familiar syntax and terminology (i.e., File Section, Working-Storage Section, and so forth) when you use COBOL .NET [2] as your .NET language of choice. Given that you are assuming a bilingual programming retraining approach (COBOL .NET and VB .NET), you already have a head start.
So now you'll examine some code snippets to see how this looks in practice (both past and current). The legacy mainframe COBOL code snippet in Listing 6-1 should look familiar.
![]() |
Data Division. File Section. . . . Working-Storage Section. 77 My-First-Number Pic S9(4) USAGE IS COMP. 77 My-Second-Number Pic S9(9) USAGE IS COMP-3. 77 My-Third-Number Pic 9(3)V99. . . . Linkage Section. . . . Procedure Division. . . .
![]() |
Listing 6-1 shows an example of defining variables. Although you will not perform a strict one-to-one type conversion (from legacy COBOL to COBOL .NET), the code snippet in Listing 6-1 will help define the context for further discussion.
Tip | From within the VS .NET IDE, while you have an existing project open , the Solution Explorer window is available to provide full access to all files that exist in your .NET solution. Learning to navigate in this window will increase your productivity during development. Be sure to familiarize yourself with the various pop-up context windows (right- click and so forth) that are accessible from within the Solution Explorer window. |
To convert the legacy COBOL example definitions in Listing 6-1 to COBOL .NET definitions (declarations), you have a choice to make. You need to decide whether to use .NET data types directly (as object references) or to use the COBOL .NET equivalent data types that are intrinsically supported. First, you'll take a look at the code, and then I'll discuss this topic further.
Using a Console Application as my Visual Studio .NET (VS .NET) COBOL template type, I have created a COBOL project and named it DefineDataTypesSampleCobol. The COBOL .NET code sample ( copied from the Program1.cob module) is presented in Listing 6-2.
![]() |
000010 IDENTIFICATION DIVISION. 000020 PROGRAM-ID. MAIN. 000030 ENVIRONMENT DIVISION. 000040 CONFIGURATION SECTION. 000050 REPOSITORY. 000060* .NET Framework Classes 000070 CLASS SYS-INT16 AS "System.Int16" 000080 CLASS SYS-INT32 AS "System.Int32" 000090 CLASS SYS-DOUBLE AS "System.Double". 000100* 000110 DATA DIVISION. 000120 WORKING-STORAGE SECTION. 000130* Declare Data Items with COBOL.NET Data Types 000140 77 My-First-Number-Intrinsic PIC S9(4) USAGE IS COMP-5. 000150 77 My-First-Number-Int8Demo PIC S9(5) USAGE IS COMP-5. 000160 77 My-Second-Number-Intrinsic PIC S9(9) USAGE IS COMP-5. 000170 77 My-Third-Number-Intrinsic USAGE IS COMP-2. 000180* Declare Data Items using .NET Data Types 000190 77 My-First-Number-ObjectRef OBJECT REFERENCE SYS-INT16. 000200 77 My-Second-Number-ObjectRef OBJECT REFERENCE SYS-INT32. 000210 77 My-Third-Number-ObjectRef OBJECT REFERENCE SYS-DOUBLE. 000220 000230 01 NULL-X PIC X(1). 000240 LINKAGE SECTION. 000250* 000260 PROCEDURE DIVISION. 000270* Move numeric literal to Data Item 000280 MOVE 32767 TO My-First-Number-Int8Demo. 000290 MOVE 32767 TO My-First-Number-Intrinsic. 000300 000310 Display "Pic5 " My-First-Number-Int8Demo 000320 Display "Pic4 " My-First-Number-Intrinsic 000330 000340 DISPLAY "Enter X and Press Enter to Exit.". 000350 ACCEPT NULL-X. 000360* 000370 END PROGRAM MAIN.
![]() |
Note | On lines 20 and 370, the PROGRAM-ID has been changed to MAIN. You will need to modify the ENTRY NAME on the PROPERTY PAGES for this project to reflect the value of "MAIN." I generally follow this approach in the remaining samples in this chapter. |
As you can see, the code is not performing any logic yet, hence the empty Procedure Division. You will fill in the Procedure Division in a later section (in the section titled "Logic Statements"). Notice that there is a correlation between the fields suffixed with "Intrinsic" and those suffixed with "ObjectRef". The first set of fields (lines 140 through 170) consists of COBOL .NET data types that have an equivalent mapping to the corresponding .NET data type.
Cross-Reference | I expand on the topic of variable declaration and include examples of other data types (i.e., Strings and Booleans) in the section "Logic Statements" later in this chapter. There are other intrinsically supported data types. Please refer to the COBOL .NET documentation for a complete list. |
You may have noticed that I haven't yet discussed a few things in the COBOL .NET code in Listing 6-2. For example, lines 70 through 90 present an example of using three classes from the .NET Framework. I discuss this type of .NET Framework usage and much more in Chapter 7.
Additionally, notice the use of the REPOSITORY paragraph on line 50. The REPOSITORY paragraph represents an area where you will store information about classes, interfaces, functions, and properties. In the previous COBOL .NET sample code, you are using the REPOSITORY as a place to connect your "internal" variables (those defined with the "ObjectRef" suffix) to the class name of the referenced .NET Framework class. Again, when I discuss the .NET Framework in Chapter 7, you will see much more usage of the REPOSITORY paragraph.
The OBJECT REFERENCE clause may look new to most of you. However, if you refer back to your advanced legacy mainframe COBOL experience, you may recall coding statements that included a USAGE IS POINTER clause. You would have used this clause following the PICTURE clause for a data item definition. Subsequently, you were likely to use the ADDRESS OF special register along with a SET statement. Sound familiar? Good, then you have an idea of what the OBJECT REFERENCE is accomplishing in the COBOL .NET example in Listing 6-2 (lines 190 through 210). Nevertheless, I further discuss this topic of referencing objects in Chapter 9.
Typically, you would not include a complete set of definitions using both approaches as I have in the COBOL .NET code example in Listing 6-2. I did this just for demonstration purposes. These declarations demonstrate a choice that is available when you code your COBOL .NET declarations. So, what difference does it make when you choose one way or the other to define your variables?
There is one opinion that says to give preference to the COBOL .NET data types over the .NET data types. A few reasons that may support this opinion are as follows :
If you use .NET data types that are value types, [3] the entire object, not just the pointer, is allocated in your Working-Storage area.
If you use .NET data types, you will need to write extra lines of programming code.
Fujitsu must have had a good reason for going to the trouble of making sure that many of the COBOL .NET data types map directly to the .NET data types. The opposite was more likely ”they probably wanted to map all of the .NET data types back to COBOL .NET data types.
There is another opinion that says to go ahead and create the object references and use the .NET Framework classes directly. Some reasons that may support this opinion are as follows:
The .NET Framework classes have valuable built-in methods and properties.
The more you use the .NET Framework classes, the quicker you will learn how to leverage .NET technology in general.
The average VB .NET programmer will be able to understand and maintain your COBOL .NET code.
Then, I have my opinion, which is plan to use both data types. When possible, use the .NET Framework classes (including the .NET data types). Otherwise, use the COBOL .NET data types, but be careful. Please keep in mind the following considerations:
First consideration: For those who would avoid the .NET data types just because of the way that the Working-Storage memory allocation is handled for value types, I kindly remind them of the last time that COBOL programmers made design sacrifices to save a negligible amount of memory (remember Y2K?). Times have changed, and memory is cheaper and more available.
Second consideration : The built-in properties and methods available to users of .NET data types offer significant value. Yes, there is the ToString method that can convert the typical .NET data type to a String . I say, go for any chance to use .NET Framework classes and any built-in methods and/or properties. To me, this type of "reusability" is one important step toward an OOP mindset.
Third consideration : Use the .NET Framework members as much as possible. The more you use them, the more familiar you will become with them. This will lead to a definite increase in programming productivity. How? You will begin to use many other built-in methods and properties and thus write less duplicate code. In Chapter 7, you will explore many of these .NET Framework members.
Fourth consideration: Plan to use both approaches, but do be careful. When you need to manipulate indexes and perform mathematical problems, the COBOL .NET data types are likely your best choices. When you need to pass data items between .NET programs, typically you will choose the .NET data types. [4] Nevertheless, choose your data types carefully . For example, you could end up inadvertently truncating your data. In some cases, the compiler will produce code for you that I feel is not intuitive. I believe this will be a source of hidden program bugs for those who approach this topic without caution.
Let's dig deeper into the fourth consideration. Take, for example, the following COBOL .NET code snippet:
...PIC S9(4) USAGE IS COMP-5.
As explained in Fujitsu's COBOL .NET documentation, this type of data declaration is intended to map directly to the .NET type System.Int16 , a 16-bit signed integer. (I prove later in the section "Examining Microsoft Intermediate Language" that this mapping actually does occur.)
This is a good thing. However, it is not so good when you attempt to move data into your COBOL .NET data type field. As it turns out, the maximum useable value for a field, using the definition shown previously, is 9999. You might say, "Chris, that is fine. It is, after all, a four-digit PICTURE clause."
The concern that I have is that it does map directly to a 16-bit signed integer .NET data type. This becomes more of a concern when you take into consideration that (according to .NET's documentation) the 2-byte System.Int16 data type should have a maximum value range of “32768 to 32767. Please take note that this value range is significantly more than maximum useable value 9999 (the word "useable" is a hint here). Well, if you move the value of 32767 to the "intrinsically" supported COBOL .NET data type, your high-order digit is truncated, resulting in a stored value of 2767. As shown in the following code snippet, the value of 32767 is being moved to the field in question (My-First-Number-Intrinsic):
... 000270* Move numeric literal to Data Item 000280 MOVE 32767 TO My-First-Number-Int8Demo. 000290 MOVE 32767 TO My-First-Number-Intrinsic. 000300 000310 Display "Pic5 " My-First-Number-Int8Demo 000320 Display "Pic4 " My-First-Number-Intrinsic 000330 000340 DISPLAY "Enter X and Press Enter to Exit.". 000350 ACCEPT NULL-X. 000360* 000370 END PROGRAM MAIN.
How nice! I do not think so. Interestingly enough, the compiler generates the following warning message and compilation completes with a "Build Succeeded" message:
JMN3328I-W WHEN NUMERIC LITERAL IS MOVED TO 'MY-FIRST-NUMBER-INTRINSIC' IN MOVE STATEMENT,OVERFLOW IS OCCURRED.
Doesn't this remind you of "condition code 4"s from the legacy mainframe COBOL compiles? Because compilation was usually allowed to complete with a "condition code 4," some developers habitually ignored those innocent warning messages. Later, after they got burned a few times, experienced developers learned that there is no such thing as an innocent warning message. I believe those lessons learned still apply here with COBOL .NET.
Note | I find it somewhat interesting that attempting to move 99999 into the field also produces an OVERFLOW compile error. However, in this case, the severity of the message is high enough to prevent compilation from continuing. Following the attempted compilation, the VS .NET IDE Task window will display the recommended correction. |
You may ask, "Why not just bump the PICTURE size from 9(4) to 9(5)?" Well, if you do that, you are no longer mapping directly to the .NET System.Int16 data type; rather, you are mapping to the unsigned Int8 data type (also known as System.BYTE ). I prove this in the section "Examining Microsoft Intermediate Language," where you will take a look at the MSIL that is being generated behind the scenes.
To that, perhaps you might respond, "So what, I'm mapping to the Int8 instead of System.Int16. At least the number value isn't truncated now." The thing that puzzled me is that if you're mapping to Int8, then you're essentially mapping to the .NET data type System.BYTE. As you may have guessed, System.BYTE has a value range of 0 to 255. Therefore, why is the value of 32767 not being truncated, given that it clearly exceeds 255?
As it turns out, by changing the PICTURE size from 9(4) to 9(5), you've requested that the compiler create a zero-based , one-dimensional array. Isn't it nice of the compiler to do this for you? (I'm being sarcastic , by the way.) Honestly, if I really wanted to create an array, I'd prefer to do so explicitly to make what's really going on more obvious.
Note | An array is similar to the tables (sometimes referred to as arrays) that you created during your legacy mainframe COBOL experiences. With tables, you used the OCCURS clause to define how many elements were contained in the table. Sometimes you would create single- level (or one-dimensional) tables. Other times, you would create double-level (or two-dimensional) tables. Then, using a subscript or an index, you would retrieve the individual elements of your table (or array). To access the first element, you would access the element item that had an index or subscript value of "1". So, you were working with a 1-based array. |
Now, what do you think about using the COBOL .NET data types? I guess this is what Fujitsu meant by providing "intrinsic" support. One minute you are mapping to the System.Int16 data type (also known as the Short data type) and the next minute you are mapping to a one-dimensional array of type Int8.
Note | The Help text provided with VS .NET does state that there is general memory overhead associated with arrays (" . . .an array uses extra memory for the array itself and also for each dimension . . . this overhead is currently 12 bytes plus 8 bytes for each dimension. . .. "). So, if you are avoiding object references in an attempt to save memory, you may be introducing more memory usage than the amount you are trying to save. |
My suggestion is to choose your approach to creating your data types carefully. Choose your data types even more carefully. Plan to use both approaches: COBOL .NET intrinsic data types and native .NET data types. You will notice that in the sample code in this book, I restrict my usage of these COBOL .NET data types to manipulating indexes and some arithmetic functionality. To Fujitsu's credit, I am glad they built in the ability to declare data items using either approach. That way, you do have a choice.
![]() |
Why does Fujitsu care (and why should you care) whether the COBOL .NET language provides direct intrinsic support for the .NET data types? The question of being Common Language Specification (CLS) compliant is what it boils down to. When you take the bold step to .NET-enable your language compiler (as Fujitsu has), being CLS compliant is one measure of just how .NET-enabled the language compiler is. Although there are many requirements for such compliance, supporting (intrinsically) the main .NET data types is obviously one such requirement. (See the "Web Sites" subsection in the "To Learn More" section at the end of this chapter for a CLS- related link.)
![]() |
Have I exhausted the "data type with COBOL .NET" topic? All right, this seems like a good breaking point. In the next section you'll look at some VB .NET code.
Using VB .NET, I demonstrate the declaration of three numeric fields as I did in the preceding legacy COBOL and COBOL .NET code examples. Again, using a Console Application as my VB .NET template type, I have created a VB .NET project and named it DefineDataTypesSampleVB. Listing 6-3 shows the VB .NET code sample (copied from the Module1.vb module).
![]() |
Module Module1 Sub Main() 'Declare Data Items using VB .NET Data Types Dim MyFirstNumberVBNET As Short Dim MySecondNumberVBNET As Integer Dim MyThirdNumberVBNET As Double 'Declare Data Items using Native .NET Data Types Dim MyFirstNumberNative As System.Int16 Dim MySecondNumberNative As System.Int32 Dim MyThirdNumberNative As System.Double End Sub End Module
![]() |
In the VB .NET code sample in Listing 6-3, you will notice that three data items have been dimensioned (declared) using the VB .NET data types. Then, a similar set of data items has been declared using the native .NET data types.
In the case of VB .NET, there truly is not a difference between the VB .NET data types and the native .NET data types. They (intuitively) map exactly as you would expect them to. Of course, I have verified this by taking a quick look at the MSIL. (Yes, I demonstrate this in the section "Examining Microsoft Intermediate Language.") With VB .NET, use either approach.
Just to be fair, I decided that even the VB .NET sample deserved the same scrutiny as that of the COBOL .NET sample. I wanted to move a "maximum" value numeric literal into the Int16 and Short data type data items. The code snippet in Listing 6-4 demonstrates this.
![]() |
Module Module1 Sub Main() . . . 'Place a numeric literal in Data Item MyFirstNumberVBNET = 32767 MyFirstNumberNative = 32767 End Sub End Module
![]() |
As expected, both fields accepted the maximum value of 32767 without any truncation .
Tip | You have a choice between copying and pasting this source code or typing it in (line by line). If you copy and paste you can rest assured that the sample code will work (this approach avoids typos). On the other hand, you do want to start coding soon for real learning. Here, I just want to point out that both approaches offer value. (This applies to both the VB .NET samples and the COBOL .NET samples.) |
Naturally, you can only do so much with just data item declarations. In fact, you can't really do anything. Therefore, let's look at the logic statements. I like to refer to logic statements as the "glue" that holds everything else together.
Logic statements represent the real purpose of your application. After all, the reason that you are creating an application in the first place is to implement business rules, providing some type of valuable service to your business (whether directly or indirectly). Regardless of the platform, regardless of the language, this is true. [5] You have written logic statements in your legacy mainframe COBOL applications. This requirement will remain constant, even with .NET.
In your previous programming experiences, have you ever created an infinite loop? Granted, an infinite loop is not something to be proud of. Nonetheless, you are certainly familiar with the concept of conditional logic, even if the condition is never met. Of course, a program is not necessarily made up of looping logic alone.
In the samples that follow, you will take a look at logic used to perform (finite) loops . Additionally, you will review other types of logic statements (e.g., case-type statements and comparative operators). I even throw in a few intrinsic COBOL functions. In this section, you will briefly review some of the more common types of logic statements. The following types of logic statements are included in the sample code:
Conditional logic
Constants
Intrinsic functions
In the following COBOL .NET code sample, most (if not all) of what you will see should be familiar to you. I have coded this particular sample program for these reasons:
To demonstrate that you can use most of the COBOL syntax that you are already familiar with in .NET
To provide a comfortable context from which to derive future code samples for the later chapters
Following the COBOL .NET code sample, I include a VB .NET code sample. With the VB .NET sample, my assumption is that this will be a good opportunity for you to learn some more of the VB .NET syntax basics.
Using a Console Application [6] as my VS .NET COBOL template type, I have created a COBOL project and named it LogicSampleCobol. Listing 6-5 presents the COBOL .NET code sample (copied from the Program1.cob module).
![]() |
000010 IDENTIFICATION DIVISION. 000020 PROGRAM-ID. MAIN. 000030 ENVIRONMENT DIVISION. 000040 CONFIGURATION SECTION. 000050 REPOSITORY. 000060* 000070*** .NET Framework Classes 000080* 000090 CLASS SYS-STRING AS "System.String" 000100 CLASS SYS-INTEGER AS "System.Int32" 000110 CLASS SYS-BOOLEAN AS "System.Boolean". 000120* 000130 DATA DIVISION. 000140 WORKING-STORAGE SECTION. 000150* 000160*** Declare Data Items using .NET Data Types 000170* 000180 01 MY-String OBJECT REFERENCE SYS-STRING. 000190 01 MY-Integer OBJECT REFERENCE SYS-INTEGER. 000200 01 MY-Boolean OBJECT REFERENCE SYS-BOOLEAN. 000210* 000220*** Declare Data Items with COBOL .NET Data Types 000230* 000240 01 My-Index PIC S9(9) COMP-5. 000250 01 My-SecondIndex PIC S9(9) COMP-5. 000260 01 My-Accum PIC S9(9) COMP-5. 000270 01 My-Flag PIC 1 USAGE BIT. 000280 88 My-Flag-True Value B'1'. 000290 88 My-Flag-False Value B'0'. 000300 01 NULL-X PIC X(1). 000310 01 SystemDate. 000320 05 YYYY PIC 9999. 000330 05 MM PIC 99. 000340 05 DD PIC 99. 000350 01 My-FixedLengthString PIC X(50). 000360* 000370*** Demonstrate creation of Table-Array 000380* 000390 01 MONTH-VALUES. 000400 05 PIC X(09) VALUE "January". 000410 05 PIC X(09) VALUE "February". 000420 05 PIC X(09) VALUE "March". 000430 05 PIC X(09) VALUE "April". 000440 05 PIC X(09) VALUE "May". 000450 05 PIC X(09) VALUE "June". 000460 05 PIC X(09) VALUE "July". 000470 05 PIC X(09) VALUE "August". 000480 05 PIC X(09) VALUE "September". 000490 05 PIC X(09) VALUE "October". 000500 05 PIC X(09) VALUE "November". 000510 05 PIC X(09) VALUE "December". 000520 01 MONTH-TABLE REDEFINES MONTH-VALUES. 000530 05 MONTH-ITEMS OCCURS 12 TIMES. 000540 10 MONTH-ITEM PIC X(9). 000550 PROCEDURE DIVISION. 000560* 000570*** Demonstrate Intrinsic Function accessing System Date 000580* 000590 MOVE FUNCTION CURRENT-DATE TO SystemDate 000600 DISPLAY "Today is " SystemDate 000610 000620* 000630*** Demonstrate Boolean fields, Constants, Conditional/Computational Logic 000640* 000650 PERFORM UNTIL My-Flag = B"1" 000660 ADD 1 TO My-Index 000670 IF My-Index > 12 000680 SET MY-Boolean to B"1" 000690 SET My-Flag to MY-Boolean 000700 END-IF 000710 END-PERFORM 000720 IF My-Flag-True Then 000730 SET MY-String to "The 88 Level Boolean is now set to TRUE" 000740 SET My-FixedLengthString to MY-String 000750 DISPLAY My-FixedLengthString 000760 END-IF 000770* 000780*** Demonstrate usage of Conditional and Computational Logic 000790* 000800 PERFORM VARYING My-SecondIndex 000805 FROM 0 BY 1 UNTIL My-SecondIndex = My-Index 000810 COMPUTE My-Accum = My-SecondIndex + 1 000820 END-PERFORM 000830 SET MY-Integer to My-Accum 000840* 000850*** Demonstrate Intrinsic Functions, Conditional and Computational Logic 000860* 000870 MOVE 1 to My-Index 000880 INITIALIZE My-FixedLengthString 000890 PERFORM 12 TIMES 000900 EVALUATE MONTH-ITEM (My-Index) 000910 WHEN "December" 000920 WHEN "January" 000930 WHEN "February" 000940 STRING 000950 MONTH-ITEM (My-Index) DELIMITED BY " " 000960 " " DELIMITED BY SIZE 000970 "is" DELIMITED BY SIZE 000980 " " DELIMITED BY SIZE 000990 "Winter" DELIMITED BY SIZE 001000 INTO My-FixedLengthString 001010 END-STRING 001020 DISPLAY My-FixedLengthString 001030 INITIALIZE My-FixedLengthString 001040 WHEN "March" 001050 WHEN "April" 001060 WHEN "May" 001070 STRING 001080 MONTH-ITEM (My-Index) DELIMITED BY " " 001090 " " DELIMITED BY SIZE 001100 "is" DELIMITED BY SIZE 001110 " " DELIMITED BY SIZE 001120 "Spring" DELIMITED BY SIZE 001130 INTO My-FixedLengthString 001140 END-STRING 001150 DISPLAY My-FixedLengthString 001160 INITIALIZE My-FixedLengthString 001170 WHEN "June" 001180 WHEN "July" 001190 WHEN "August" 001200 STRING 001210 MONTH-ITEM (My-Index) DELIMITED BY " " 001220 " " DELIMITED BY SIZE 001230 "is" DELIMITED BY SIZE 001240 " " DELIMITED BY SIZE 001250 "Summer" DELIMITED BY SIZE 001260 INTO My-FixedLengthString 001270 END-STRING 001280 DISPLAY My-FixedLengthString 001290 INITIALIZE My-FixedLengthString 001300 WHEN "September" 001310 WHEN "October" 001320 WHEN "November" 001330 STRING 001340 MONTH-ITEM (My-Index) DELIMITED BY " " 001350 " " DELIMITED BY SIZE 001360 "is" DELIMITED BY SIZE 001370 " " DELIMITED BY SIZE 001380 "Autumn" DELIMITED BY SIZE 001390 INTO My-FixedLengthString 001400 END-STRING 001410 DISPLAY My-FixedLengthString 001420 INITIALIZE My-FixedLengthString 001430 END-EVALUATE 001440 ADD 1 to My-Index 001450 END-PERFORM 001460 DISPLAY "Enter X and Press Enter to Exit.". 001470 ACCEPT NULL-X. 001480* 001490 END PROGRAM MAIN.
![]() |
If you were to run this program, you would produce a console window display as shown in Figure 6-1.
Please take a moment and familiarize yourself with this program. Remember, you will derive future sample code snippets from this sample application.
Tip | You have probably noticed that I included comments in the sample code. Even with .NET, good programming practices still apply. Rather than restate what has already been included in the preceding sample code (if you do not mind), I will simply refer you to the following sample code comment lines: 370, 570, 630, 780, and 850. That is it ” a new look at some old programming practices. |
Note | The "current date" logic (lines 590 and 600) will retrieve and display your system date at runtime. |
Before you move on to the VB .NET sample code, I would like to mention a great VS .NET feature at this time: the Clipboard Ring.
During your coding experience, there will be times when rather than repeatedly type something you'll choose to copy and paste. Everyone does this. It's not because we're lazy; rather, we're cost conscious and seek to improve our productivity. Well, with the VS .NET IDE feature called the Clipboard Ring, your productivity just received another boost.
To use the Clipboard Ring (while viewing your .NET program in the VS .NET IDE), you will first need to display the Toolbox. To do this, choose View Toolbox. The icon and menu option associated with the Toolbox are shown in Figure 6-2.
The next step is to select the program code lines that you want to copy (or cut). You can use the options displayed on the Standard toolbar for this. Notice that in Figure 6-3, I have selected three lines of code and subsequently copied them.
You will notice that after "copying" the selected text, an item shows up in the Clipboard Ring (as shown in Figure 6-3). Items will continue to accumulate as you repeat the select and copy steps. You will realize the true value of the Clipboard Ring as you drag and drop these accumulated items one by one (in any order) from the Clipboard Ring to targeted areas in your program modules. Whether you are working with text-formatted files in your COBOL .NET projects or your VB .NET projects, you will notice that this great VS .NET IDE feature is available.
Staying with the Console Application template type, I have created a new project in VS .NET with VB .NET as the language choice. The new project is named LogicSampleVB. Listing 6-6 presents the VB .NET code sample (copied from the Module1.vb module [7] ).
![]() |
Module Module1 Sub Main() '* '*** Declare Data Items using .NET Data Types '* Dim MYString As System.String Dim MYInteger As System.Int32 Dim MYBoolean As System.Boolean '* '*** Declare Data Items with Visual Basic.NET Data Types '* Dim MyIndex As Integer Dim MySecondIndex As Integer Dim MyAccum As Integer Dim MyFlag As Boolean Dim systemDate As Date Dim MyFixedLengthString As String '* '*** Demonstrate creation of String Array '* Dim MonthValues() As String = _ {"January", "February", "March", _ "April", "May", "June", _ "July", "August", "September", _ "October", "November", "December"} '* '*** Demonstrate Intrinsic Function accessing System Date '* systemDate = Now Console.WriteLine("Today is " & systemDate.ToShortDateString) '* '*** Demonstrate Booleans, Constants, and Conditional/Computational Logic '* Do Until MyFlag = True MyIndex += 1 If MyIndex > 12 Then MYBoolean = True MyFlag = MYBoolean End If Loop If MyFlag Then MYString = "The Boolean is now set to TRUE" MyFixedLengthString = MYString Console.WriteLine(MyFixedLengthString) End If '* '*** Demonstrate usage Conditional and Computational Logic '* For MySecondIndex = 1 To MyIndex MyAccum = MySecondIndex + 1 Next MySecondIndex MYInteger = MyAccum '* '*** Demonstrate Intrinsic Functions, Conditional/Computational Logic '* MyIndex = 1 MyFixedLengthString = String.Empty Dim x As Int32 For x = 0 To 11 Select Case MonthValues(x) Case "December", "January", "February" Console.WriteLine _ (MyFixedLengthString.Concat(MonthValues(x), _ " is ", "Winter")) Case "March", "April", "May" Console.WriteLine _ (MyFixedLengthString.Concat(MonthValues(x), _ " is ", "Spring")) Case "June", "July", "August" Console.WriteLine _ (MyFixedLengthString.Concat(MonthValues(x), _ " is ", "Summer")) Case "September", "October", "November" Console.WriteLine _ (MyFixedLengthString.Concat(MonthValues(x), _ " is ", "Autumn")) End Select Next Console.WriteLine("Press Enter to Exit") Console.ReadLine() End Sub End Module
![]() |
Note | I hope that you have started experiencing the VS .NET IDE. Whether you have chosen to type the sample code or to copy and paste the code, it is time to get your hands dirty . |
Now that you have had a chance to view the sample VB .NET code in Listing 6-6, what do you think? Which do you think is easier or more straightforward: COBOL .NET or VB .NET? Can I ask that you hold that thought? I do not think it is fair to judge either language yet. How one language or the other implements the features of .NET will vary ”that is a fact. Moreover, that is my point: You are just beginning to scratch the surface. Please wait until you have read a few more chapters in this book before you make this sort of judgment. At that time, you will be well prepared to weigh in on one side or the other. In the meantime, you have to admit that being bilingual is actually rather cool.
To wrap up this sample code section, let's run the VB .NET sample program. The program produces the console window display shown in Figure 6-4.
In the preceding section, I suggested that you delay judgment of the two languages. However, that does not mean that you cannot make note of your observations and even formulate constructive criticism. In previous sections, you have worked with the basic programming syntax (both with COBOL .NET and VB .NET). Undoubtedly, working with the previous sample applications has given you a glimpse into a few feature differences.
Throughout this book, I will point out any product features that may be available in one language (i.e., VB .NET), but not available in the other language (i.e., COBOL .NET). I suspect that this will typically position VB .NET to sit on the "available" side of the comparison. Consequently, you might consider creating your own "wish list." Then, you could use your wish list as a constructive communication vehicle to forward to Fujitsu Software Corporation.
What does this say about COBOL .NET's feature set? Well, if my opinion about COBOL .NET's feature set was based solely on pointing out the things that Fujitsu's product was missing (when compared to VB .NET), I would be left with a slightly negative opinion. But, that is just it. I am not basing my opinion on what COBOL .NET is missing. Rather, it is what COBOL .NET is not missing that makes it a .NET language worthy of consideration.
![]() |
Considering that Fujitsu's NetCOBOL for .NET product is in an early version (currently v1.1), Fujitsu has done an outstanding job. The product actually works! Not many companies can say that about their early product releases. (By the way, you can also include Microsoft in this distinguished category. Remember, this is also an early version ”currently going from v1.0 to v1.1 ”of the entire .NET platform. I take my hat off to both companies.)
Additionally, it appears to me that we (the mainframe community) owe it to ourselves and to Fujitsu to embrace and support this product. I applaud Fujitsu for supporting the COBOL language. The least that we can do is support the COBOL .NET product. Allow me to point out that the long- term success of this product (any product, for that matter) is directly related to the support (adoption, use, and interest) received from its users.
Lastly, it should be noted that Fujitsu's software support group has been extremely responsive . I have been left with the impression that some (if not all) of the feature differences will be addressed in future releases of the NetCOBOL for .NET product. I suggest that we use Fujitsu's product, make notes of any improvement opportunities, and forward our constructive feedback directly to Fujitsu. [8] Together, we can help what is now a good product become an even bet-ter, more feature-rich product.
![]() |
Included with your NetCOBOL for .NET product installation are a generous number of code samples. You can locate these code samples by browsing the specific hard disk location where the Fujitsu NetCOBOL for .NET product is installed on your machine and navigating to the Examples subfolder. The typical installed disk location is
<Hard drive>:\Program Files\Fujitsu NetCOBOL for .NET\Examples
I have browsed these samples and found them to be very useful. You should spend some time familiarizing yourself with them. The samples I have provided in this book will serve as a complement to the ones provided by Fujitsu. I have made an attempt to not duplicate the Fujitsu samples.
Note | Naturally, the samples provided by Fujitsu are in COBOL .NET only. That makes the bilingual approach (i.e., samples in both COBOL .NET and VB .NET) of this book slightly unique. |
Rather, I preferred to add value by seeking out alternatives, variations, and extensions in my own "simple" code examples. When you combine both sets of samples together, you should have more than enough to get you off to a good start. Nevertheless, you will notice that my sample code and Fujitsu's provided samples both take a simplistic approach, avoiding a realistic business rule approach. Most agree that this approach allows for more focus on the actual technology.
Consider leveraging the VS .NET IDE toolset to help you explore these sample applications. In the next section I introduce to you the Solution Explorer window, a VS .NET IDE tool. This is one VS .NET IDE tool that you may find yourself using quite often.
In Chapter 5, I referred to the Solution Explorer window, which you can access by selecting View Solution Explorer or pressing Ctrl-Alt-L. You used this window to access the property pages of the project. Well, there are a few other treats awaiting your discovery with the Solution Explorer. As shown in Figure 6-5, not only can you view your editable program modules, but you can also use the Show All Files feature to view all the files stored in your local application path .
You will notice that the display style is that of a collapsible tree. You will also notice that the top item on the tree is the solution file (in this case, LogicSampleVB.sln). In this solution file, you can have one or more projects. The second item from the top of the tree is the project file (in this case, LogicSampleVB.vbproj). Basically, all of the files related to your project will be stored "under" the project in question. As shown in Figure 6-5, even the executable file (LogicSampleVB.exe) falls under the project. Please note the executable file (EXE) is stored in a subfolder named bin. If you were creating dynamic link library (DLL) files instead of executable files, you would see the DLL file in the bin subfolder as well.
Note | In some .NET languages, a .NET assembly can consist of one or more DLL files or EXE files. In VB .NET and COBOL .NET, an assembly is composed of just one EXE or one DLL. For our purposes, the term "assembly" can be used loosely as a synonym for executable or dynamic link library. The AssemblyInfo.vb file that appears in the Solution Explorer can be used to provide metadata for the assembly. |
This brief introduction to the Solution Explorer should be sufficient for now. I reference the Solution Explorer in this book when it is useful to do so. In the meantime, go ahead and explore and discover. I encourage you to further explore the Solution Explorer feature of VS .NET.
[2] Just a kind reminder: "COBOL .NET" is my own unofficial reference to Fujitsu's NetCOBOL for .NET product.
[3] I explain the concept of value types further in Chapters 8 and 9.
[4] In Chapter 20, I discuss data marshaling. At that time, I make a distinction between the concerns of marshaling data items (whether native .NET data types or not) and objects (whether managed .NET objects or not).
[5] Unless, of course, you are writing programs as a hobby sitting at home.
[6] In Chapter 13, I introduce other template types (i.e., Windows, ASP.NET, and Web services). For now, I am limiting the samples to the use of the Console Application template. This is intended to encourage more focus on other targeted topics.
[7] In your own, real-life projects, you will choose to name your modules appropriately. For simplicity's sake, I left the modules with their default names .
[8] You can e-mail Fujitsu Software's technical support directly. Optionally, feel free to forward an e-mail to me and I will forward it to Fujitsu. Include the description "COBOL .NET Wish List" in the e-mail subject header. My e-mail address is Richardson@eClecticSoftwareSolutions.com .