Try OpenEdge Now
skip to main content
GUI for .NET Mapping Reference
Mapping Reference Entries : C# .NET code mapped to OpenEdge GUI for .NET ABL
 

C# .NET code mapped to OpenEdge GUI for .NET ABL

The following table compares features of C# .NET code with similar features in ABL code using the OpenEdge GUI for .NET, listed in approximate order of definition and usage.
Table 1. C# .NET code mapped to OpenEdge GUI for .NET ABL
Feature
Microsoft .NET C#
OpenEdge GUI for .NET ABL
Object type-name syntax
C# Syntax
[namespace . ]dotNET-object-name
  [.inner-type-name]
Example .NET type names:

System.Windows.Forms.Control
System.Windows.Forms.Control.ControlCollection
System.Drawing.Point[]
ABL Syntax
[" ]
  [namespace . ]
dotNET-object-name   
[
+inner-type-name]
[" ]
Example .NET type names:

System.Windows.Forms.Control

System.Windows.Forms.Control+ControlCollection

"System.Drawing.Point[]"
Allowing unqualified type references
C# Syntax
using namespace;
Example:

// Unqualified reference to
// all types in a namespace
using System.Windows.Forms;
ABL Syntax

USING namespace.*[ FROM ASSEMBLY ] .
USING namespace.type-name
  [ FROM ASSEMBLY ] .
Examples:

/* Unqualified reference to
   all types in a namespace */
USING System.Windows.Forms.*
  FROM ASSEMBLY.
/* Unqualified reference to
   the Button class type    */
USING
System.Windows.Forms.Button
  FROM ASSEMBLY.
Class instantiation
C# example:

using System.Windows.Forms;

Button rButton = new Button( );
ABL example:

USING System.Windows.Forms.*
  FROM ASSEMBLY.

DEFINE VARIABLE rButton AS Button.
rButton = NEW Button( ).
Type casting1
C# example:

using System.Windows.Forms;

Control rControl = new Control( );
Button rButton = new Button( );

rControl = rButton;
rButton = (Button) rControl;
ABL example:

USING System.Windows.Forms.*.

DEFINE VARIABLE rControl AS Control.
DEFINE VARIABLE rButton  AS Button.
rControl = NEW Control( ).
rButton = NEW Button( ).
rControl = rButton.
rButton = CAST ( rControl, Button ).
Instance member reference
C# Syntax
object-reference.member-reference
Example:

using System.Windows.Forms;
Button rButton = new Button( );
rButton.Left = 10; /* Property ref. */
rButton.Focus( );  /* Method call */
ABL Syntax
object-reference:member-reference
Example:
USING System.Windows.Forms.*
  FROM ASSEMBLY.
DEFINE VARIABLE rButton AS Button.
rButton = NEW Button( ).
rButton:Left = 10. /* Property ref. */
rButton:Focus( ).  /* Method call */
Static member reference
C# Syntax
object-type-name.member-reference
Example:
using System.Windows.Forms;
MessageBox.Show(
  System.Math.PI.ToString( ) );
ABL Syntax
object-type-name:member-reference
Example:
USING System.Windows.Forms.*
  FROM ASSEMBLY.
MessageBox:Show(
  STRING(System.Math:PI) ).
Creating and using .NET array objects
C# example:
using System.Windows.Forms;





Button[] btnArrayObj
  = new Button[ 3 ];
btnArrayObj[0] = new Button( );
ABL examples:
USING System.Windows.Forms.*
  FROM ASSEMBLY.
USING Progress.Util.*
  FROM ASSEMBLY.

/*Creating and using a
  .NET array object directly */
DEFINE VARIABLE btnArrayObj
  AS "System.Array".
btnArrayObj
  = System.Array:CreateInstance(
      TypeHelper:GetType( "Button" ),
      3 ).
btnArrayObj:SetValue( NEW Button( ),
                      0 ).

/* Creating and using an
   ABL object array to create a
   .NET array object by mapping */DEFINE VARIABLE btnArrayObj
  AS "Button[]".
DEFINE VARIABLE btnArray
  AS Button EXTENT 3.
btnArray[1] = NEW Button( ).btnArrayObj = btnArray.
Class definition2
C# sample:
using System.*;
using System.Windows.Forms;
using System.Collections;
using System.Windows.Forms.Layout;

public class
  Control.ControlCollection :
  ArrangedElementCollection,
  IList, ICollection,
  IEnumerable, ICloneable {
  . . .
}
ABL equivalent:
USING System.*.
USING System.Windows.Forms.*.
USING System.Collections.*.
USING System.Windows.Forms.Layout.*.

CLASS
  Control+ControlCollection
  INHERITS ArrangedElementCollection
  IMPLEMENTS IList, ICollection,
    IEnumerable, ICloneable :
  . . .
END CLASS.
Method calling and overriding in class hierarchy3
Example inherited C# method:
protected virtualbyte[] DoOp1 (
      decimal x,
  refshort   y,
  outulong   z
) { . . . }
Example C# usage of inherited .NET DoOp1( ) method:
// Calling DoOp1 within hierarchy
byte[] arr;
decimal x;
short y;
ulong z;


arr = DoOp1( x, ref y, out z );



// Overriding DoOp1
public override
  byte[] DoOp1 (
      decimal x,
  refshort   y,
  outulong   z
) { . . . }
Example ABL usage of inherited .NET DoOp1( ) method:
/* Calling DoOp1 within hierarchy */
DEFINE VARIABLE arr AS INTEGER
  EXTENT NO-UNDO.
DEFINE VARIABLE x AS DECIMAL NO-UNDO.
DEFINE VARIABLE y AS INTEGER NO-UNDO.
DEFINE VARIABLE z AS DECIMAL NO-UNDO.

arr = DoOp1( INPUT        x,
             INPUT-OUTPUT y,
             OUTPUT       z ).

/* Overriding DoOp1 */
METHOD PUBLIC OVERRIDE    
"System.Byte[]" DoOp1(
  INPUT        x AS DECIMAL,
  INPUT-OUTPUT y AS SHORT,
  OUTPUT       z AS UNSIGNED-INT64
) : . . . END METHOD.
Event declaration and subscription
C# event declaration and delegate for the .NET FormClosing event:
using System.Windows.Forms;

// Event declaration
public event FormClosingEventHandler
  FormClosing;

// Event delegate
public delegate void
FormClosingEventHandler (
  System.Object sender,
  FormClosingEventArgs e
)
C# example event subscription and handler:
using System.Windows.Forms;


Form rFrm = new Form( );


. . .
// Subscribe handler to event
rFrm.FormClosing += new  
Form.FormClosingEventHandler(
    rFrm_FormClosing);
. . .
private void rFrm_FormClosing(
  System.Object sender,
  FormClosingEventArgs e
) { . . . }
ABL example event subscription and handler:
USING System.Windows.Forms.*
  FROM ASSEMBLY.

DEFINE VARIABLE rFrm
  AS Progress.Windows.Form NO-UNDO.
rFrm = NEW Form( ).
. . .
/* Subscribe handler to event */
rFrm:FormClosing:Subscribe(
  rFrm_FormClosing )
.
. . .
METHOD PRIVATE VOID rFrm_FormClosing(
  sender AS System.Object,
  e      AS FormClosingEventArgs
) : . . . END METHOD.
Publishing an event in a derived class
.NET method that fires a FormClosing event:
protected virtual void OnFormClosing
(
  FormClosingEventArgs e
)
Example of publishing the event in a C#-derived .NET class:
using System.Windows.Forms;

FormClosingEventArgs rClosingArgs
  = new FormClosingEventArgs(
          CloseReason:UserClosing,
          FALSE
        );

. . .

/* Publish FormClosing event */
OnFormClosing( rClosingArgs );
Example of publishing the event in an ABL-derived .NET class:
USING System.Windows.Forms.*
  FROM ASSEMBLY.

DEFINE VARIABLE rClosingArgs
  AS FormClosingEventArgs NO-UNDO.

rClosingArgs
  = NEW FormClosingEventArgs(
          CloseReason:UserClosing,
          FALSE
        ).
. . .
/* Publish FormClosing event */
OnFormClosing( rClosingArgs ).
Enumeration types and operations
In .NET, you can operate on enumeration types using the same operators defined for integral primitive types. For example, an operator such as + is overloaded for both the C# int and enumeration types.



C# use of an enumeration type:
using System.Windows.Forms;


Button rBtn = new Button( );


rBtn:Anchor = AnchorStyles.Bottom &
              AnchorStyles.Left;
In ABL, there is no operator overloading and .NET enumerations are treated only as class-based objects. To support operations on .NET enumerations, OpenEdge provides Progress.Util.EnumHelper, a .NET helper class that defines the following static methods you can use to operate on enumeration objects as System.Enum types: Add( ), And( ), AreEqual( ), AreNotEqual( ), Complement( ), IsGreater( ), IsGreaterOrEqual( ), IsLess( ), IsLessOrEqual( ), Or( ), Subtract( ), and Xor( )
ABL use of an enumeration type:
USING System.Windows.Forms.*.
USING Progress.Util.*.

DEFINE VARIABLE rBtn AS Button.
rBtn = NEW Button( ).

rBtn:Anchor = CAST( EnumHelper:AND  ( AnchorStyles:Bottom,
    AnchorStyles:Left ),   AnchorStyles     ).
Indexed properties
.NET has a concept both of non-default indexed properties and default properties (also referred to as indexers or indexed properties). Virtually all indexed properties in the .NET Framework are indexers defined with the default property name Item.
The following code shows a sample C# indexer declaration you might find in .NET documentation for an Item property, in this case on the ControlCollection class:
using System.Windows.Forms;

// C# indexer declaration
public virtual Control this [
  int index] { get; }
Example C# indexer access on a ControlCollection object:
Control rCtrl;
ControlCollection rCol = new
  ControlCollection( . . . );
. . .






rCtrl = rCol[ 1 ];
ABL documentation refers to .NET non-default indexed properties simply as indexed properties and refers to .NET default properties (or indexers) as default indexed properties. However, most indexed properties you are likely to access are default indexed properties.
Where C# considers the indexer to be the indexed property, ABL refers to an indexer as the subscript syntax used to access a default indexed property, which you can access in one of two ways. In C#, you can only access a default indexed property using an indexer on a reference to a class instance. However, ABL allows you to access a default indexed property using the indexer either on the property name (Item) or on a reference to the class instance.

Example ABL default indexed property access on a ControlCollection object:
USING System.Windows.Forms.*.

DEFINE VARIABLE rCtrl AS
  Control NO-UNDO.
DEFINE VARIABLE rCol AS
  Control+ControlCollection NO-UNDO.
rCol = NEW
  Control+ControlCollection( . . . ).

/* Next two lines are equivalent */
rCtrl = rCol[ 1 ].
rCtrl = rCol:Item[ 1 ].
Boxing and unboxing support
Boxing is the process of converting a value type (such as a C# int or .NET System.Int32) to a reference type object. Boxing a value type wraps the value inside a System.Object. Unboxing extracts the value type from the object. Boxing and unboxing between a value type and System.Object can occur during assignment or parameter passing.
In C#, boxing is done automatically but can be done explicitly. Unboxing can only be done explicitly by casting from the System.Object to the value type you want to unbox.














C# examples:
int iNetVal = 99;
int[] iNetArr = int[3];
System.Object rBox;



rBox = iNetVal;
iNetVal = (int) rBox;
iNetVal = (System.Int32) rBox;
ABL provides three basic levels of automatic boxing and unboxing support:
*Conversion between ABL primitive types (such as INTEGER) and a .NET System.Object when you assign between them
*Conversion from an ABL array of compatible types (including ABL primitive and .NET object type elements) to a .NET System.Object when you pass the ABL array to a .NET method parameter defined as System.Object or when you assign the ABL array to a System.Object
*Conversion between compatible ABL arrays and .NET array objects for both assignment and .NET method parameter passing. Arrays are boxing-compatible between: 1) ABL arrays of primitive types and .NET arrays of corresponding implicitly mapped types (see Implicit data type mapping between ABL primitive and .NET types), and 2) ABL arrays of non-mapped .NET object types and .NET arrays of type-compatible .NET object types.
In all other situations, for example, parameter passing for ABL routines and assignment from a System.Object to an ABL primitive type, automatic boxing is not supported. Where automatic boxing is not supported, you can explicitly box and unbox between these ABL and .NET types using the ABL BOX and UNBOX built-in functions, You can also use these functions where automatic boxing is supported.
Note: Automatic boxing support between ABL arrays of primitive types and .NET arrays of implicitly mapped types does not include widening support between corresponding array elements. The array elements must be implicitly mapped.
ABL examples using iNetArr from .NET:
DEFINE VARIABLE iVal AS INTEGER.
DEFINE VARIABLE iArr AS INTEGER
  EXTENT 3 INITIAL [33,66,99].
DEFINE VARIABLE rBox
  AS System.Object.

rBox = iVal.
iVal = rBox.
rBox = iArr.
iArr = UNBOX(rBox).
iNetArr = iArr.
iArr = iNetArr.
Type conversion and mapping
In .NET, type conversion can only occur using boxing and unboxing. For more information, see the Boxing and unboxing support in this table..NET also supports aliasing between each .NET primitive type (such as C# int) and a corresponding .NET value type object (in this case, System.Int32). This allows you to assign between the primitive type and its corresponding object type and to otherwise refer to one type as the other without casting. However, this is not a type conversion, as the two types (for example, C# int and System.Int32) are really identical. Aliasing, thus, allows all .NET languages to use the same type library.
ABL also provides a form of boxing support to convert ABL primitive and array types to .NET object types (see the Boxing and unboxing support in this table).In addition, ABL supports a form of mapping between ABL primitive or array types and compatible .NET scalar or array types. For ABL primitive types, this mapping relies on existing .NET aliasing, but supports true type conversion between the ABL and corresponding .NET types. For more information, see Implicit data type mapping between ABL primitive and .NET types.4
Example of type aliasing in C#:

public intProperty1{get;set;}
public System.Int32Property2{ . . . }

Property1 = Property2;
Property2 = Property1;
Example of type mapping in ABL using Property1 and Property2 from .NET:
DEFINE VARIABLE iVal AS INTEGER.


iVal = Property1.Property1 = iVal.
iVal = Property2.Property2 = iVal.
Note: ABL provides built-in data type conversion functions that you can call to convert one ABL primitive type to another. For example, a call to INTEGER( "99" ) converts the string, "99", to the INTEGER value, 99. However, note that these functions are not casting operations. The value from a data type conversion function is not the same object represented as a new type, as in object type casting, but is actually a value of one primitive type converted to an equivalent value in another primitive type.
In addition, if you call an ABL data type conversion function on an object reference, ABL does not attempt to convert the value to the specified data type that the referenced object happens to represent. Instead, the function returns the ID of the referenced object as the primitive type specified by the conversion function:
MESSAGE "Object" INTEGER( y )
  "has the value" y
  VIEW-AS ALERT-BOX.
Thus, this statement might display the following message, where 1022 is the object ID of the System.Object referenced by y:
"Object 1022 has the value 99"
Note also that when you reference a System.Object directly in a MESSAGE statement and the System.Object represents a .NET mapped type (such as a System.Int32), the statement automatically calls the ToString( ) method on the object (in this case, y:ToString( )), which returns the object's value as a string (in this case, "99") instead of its object ID.

1 Unlike for C# and other .NET languages, ABL only supports type casting between object types. ABL supports type conversion (without the need for type casting) between compatible ABL primitive or array types and corresponding .NET types. For more information, see the Type conversion and mapping feature in this table.

2 Shown for comparison only, to illustrate how inheritance and interface implementation is indicated in C#. An ABL class would not, and cannot, implement all of the interfaces listed here (for example, IList).

3 The ABL data type keywords, SHORT and UNSIGNED-INT64, are used in these examples to explicitly map instances of a corresponding ABL primitive type (INTEGER) to specific .NET types (C# short and ulong, respectively). For more information, see the Explicit data type mapping from ABL primitive to .NET types.

4 Sometimes, you must explicitly map to a given .NET type, for example, for .NET method overloading and overriding. For more information, see the Explicit data type mapping from ABL primitive to .NET types .