METHOD-ENDMETHOD

Define a method

WSupported on Windows
USupported on Unix
VSupported on OpenVMS
NSupported in Synergy .NET
[access] [method_mod ...] METHOD name[<T[(constraints)], ...>], return_type[, options]
  parameter_def
  [constructor_init ([arguments])]
  .
  .
  .
PROC
  .
  .     ;Method implementation
  .
ENDMETHOD|END

Arguments

access

(optional) One of the following access modifiers:

PUBLIC

Access is not restricted. This is the most accessible option.

PROTECTED

Access is limited to the containing class or types derived from the containing class.

PRIVATE

Access is limited to the containing type. This is the least accessible option. (default)

INTERNAL

Access is limited to the current assembly. (Synergy .NET only)

PROTECTED INTERNAL

Access is limited to the current assembly and types derived from the containing class. (Synergy .NET only)

method_mod

(optional) One or more of the following modifiers, with the restrictions stated in the Discussion:

ABSTRACT

Must have a method implemented in a derived class of the same signature. Subclasses must implement this method.

ASYNC

Method will perform asynchronous processing. See Asynchronous processing (.NET). (Synergy .NET only)

BYREF

Indicate the return value is a reference. (Synergy .NET only)

EXTENSION

Extend the functionality of a type using a static method.

NEW

Hide an inherited member of the same name.

OVERRIDE

Override the parent class’s virtual method that has the same method signature.

PARTIAL

Method is a partial method. The return_type must be VOID. (Synergy .NET only)

READONLY

Indicates the return is read-only. (Synergy .NET only)

SEALED

Cannot be overridden any further by inheriting classes without the NEW keyword.

STATIC

Accessed without a reference object. The method can be executed even if the class that contains the method hasn’t been instantiated.

UNIQUE

Cannot be overloaded, overridden, or redeclared. (Unlike subroutines and functions, methods are not implicitly unique.)

VARARGS

More than the declared number of arguments can be passed to this routine.

VIRTUAL

Can be overridden in a subclass.

name

The name of the method to define. If you are using interfaces on .NET, this name can have the format interface.name.

T

A generic type parameter, which indicates the method is a generic method and which acts as a placeholder for which an actual type will be substituted when the member is used. Note that you can use any unused letter (not just T). See Generic types (.NET) for more information. (Synergy .NET only)

constraints

One or more of the following constraints:

Multiple constraints must be separated by commas. See Constraints for more information. (Synergy .NET only)

return_type

The return type of the method being defined. See Where data types can be used for the data types that are valid return types.

options

(optional) One of the following options:

ROUND

Use rounding rules for implied-decimal data types within the ­function.

TRUNCATE

Use truncation rules for implied-decimal data types within the ­function. (traditional Synergy only)

parameter_def

The definition of an parameter that is unique within this method. Each parameter definition has the syntax that’s described in Defining a parameter.

constructor_init

(optional) One of the following initializers:

parent

Run the parent class constructor next higher in the class hierarchy.

this

Run the current class constructor of a different signature.

arguments

(optional) One or more argument values to the constructor initializer. This value must be a literal, a STATIC field value, a CONST field value, or an argum ent name from the constructor.

Discussion

By default, a method cannot be overridden unless it is marked as ABSTRACT, OVERRIDE, or VIRTUAL. (ABSTRACT and OVERRIDE methods are also assumed to be virtual and are mutually exclusive.) A method defined with one of these modifiers is called a virtual method. An ABSTRACT method has no implementation, which means it has a PROC and an END with no intervening statements. The method in the derived class that is overriding the method in the parent class must also be marked as OVERRIDE.

A BYREF method must return a BYREF parameter, a BYREF local data field, or another BYREF method call, and that entity’s return type must be exactly the same as the BYREF method return type, with no conversions. It can’t return void, descriptors, or non-CLS types, and you can’t MRETURN a value to a method marked as BYREF. In addition, BYREF can’t be used in conjunction with the ASYNC modifier or YIELD iterators.

The READONLY modifier can only be specified in conjunction with the BYREF modifier and enables the method to return a non-modifiable reference. READONLY ensures a method’s return value can only be used in read-only scenarios—it can’t be passed as a writable argument to another method.

The SEALED modifier can only be specified in conjunction with the OVERRIDE modifier.

The EXTENSION modifier can only be specified in conjunction with the STATIC modifier. It enables you to extend a class (local or in another assembly in .NET), even if the class is declared as SEALED. An extension method must be declared in a non-generic, static class, and the first parameter type should be of the type you want to extend. The first parameter type cannot be a group, and in Synergy .NET, it cannot be a non-CLS structure.

To use an extension method, you’ll need to import the namespace that contains the class that contains the extension method and then call it using an instance of the first parameter of the extension method. (See Examples.) The class members you are using must be public. If an extension method has the same signature (minus the first parameter of the extension method) as an existing method in the class, the compiler resolves to the existing class method.

You can hide a class member in a parent class with an identical signature in an inherited class by specifying a member with the same name, along with the NEW member modifier, within the inheriting class. You can also hide dissimilar members. (For example, a field or a sealed member in the parent can be hidden by a method or field of the same name marked NEW in the child.)

The class members can be different kinds (for example, a method and a field).

In Synergy .NET, a partial class can contain a partial method, which is specified with the PARTIAL modifier. A partial method declaration consists of two parts: the definition and the implementation. These can be in separate parts of a partial class or in the same part. If none of the partial methods has an implementation, any calls to the method will be ignored. A partial method must also have at least one declaration without an implementation, or a MISDECL error is reported.

Partial methods enable the implementer of one part of the class to define a method, while the implementer of the other part of the class determines whether or not to implement the method. Partial methods must be private, must return VOID and can’t be virtual. Parameters to partial methods can’t have an OUT attribute.

The VARARGS modifier is required if you want to permit passing additional, nondeclared arguments. We recommend that you don’t use VARARGS on methods.

In the table below, a check mark indicates that the two modifiers can be used in the same method definition

Exclusivity of METHOD modifiers

Modifier

ABSTRACT

ASYNC

EXTENSION

NEW

OVERRIDE

PARTIAL

SEALED

STATIC

UNIQUE

VARARGS

VIRTUAL

ABSTRACT

ASYNC

EXTENSION

NEW

OVERRIDE

PARTIAL

SEALED

STATIC

UNIQUE

VARARGS

VIRTUAL

PRIVATE

INTERNAL

PROTECTED

PUBLIC

When used in an interface in a .NET 6 and higher project, the following modifiers are supported: PUBLIC, PRIVATE, PROTECTED, INTERNAL, SEALED, ABSTRACT, and VIRTUAL.

All defined methods are reentrant, and method data is stack based.

A program by default rounds all expression results. You can change the default to truncate in traditional Synergy by setting system option #11. However, specifying the ROUND or TRUNCATE option on a METHOD statement overrides the default rounding behavior for that function (including if system option #11 is set). You cannot specify both TRUNCATE and ROUND in the same statement. (Neither TRUNCATE nor system option #11 are supported in Synergy .NET.)

The method name (name) cannot be any of the following reserved keywords: new, parent, or value (for a property set method). Also be careful when using any other Synergy DBL keywords, such as the names of I/O statements; if the method signature coincidentally matches that of the statement with the same name, the statement will be assumed.

Asynchronous processing (.NET)

The ASYNC modifier indicates that the method will perform asynchronous processing, which means that a process can occur independently of other processes instead of being required to occur in direct succession. The method can return immediately without blocking the calling thread.

Within an asynchronous method, you must specify one or more AWAIT statements, which wait for the corresponding asynchronous task to complete. If you don’t include an AWAIT statement, your ASYNC method will not be asynchronous, because an ASYNC method does not run on its own thread.

An ASYNC method doesn’t return to its original caller until it gets to the first AWAIT statement and waits for a task that isn’t yet complete. Therefore, you should use ASYNC methods for tasks that don’t require very much thread time, and they should not perform blocking calls before their first AWAIT statement or between AWAIT statements.

An ASYNC method can contain any variable currently in scope, with the following exceptions:

Return_type must be void, Task, or Task<>. After an AWAIT expression is fully processed, a subsequent RETURN statement completes a previously returned Task<> with a final result.

A method can be both asynchronous and an iterator block, meaning an AWAIT statement and a YIELD statement can both be present in the procedure division of that method. The return type of a method that is both ASYNC and YIELD should be IAsyncEnumerable<T>, which represents an asynchronous collection.

Declaring constructor and destructor methods

You can optionally declare one or more constructor methods for a class by giving the constructor methods the same name as the class. Arguments are allowed on constructor methods to make the method signatures of the constructors unique.

You can also declare a single destructor for a class by giving the method the same name as the class with a tilde (~) appended to the beginning. See Constructors and destructors for more information.

Method implementation

You can return from a method that has a declared return type using the MRETURN statement.

Accessibility

Examples

In the example below, a method called writeit is defined.

public method writeit, void
    c2, @class2
proc
    open(1,o,"tt:")
    writes(1,"num="+%string(c2.m_number))
    close(1)
    mreturn
endmethod

The example below declares an extension method called WordCount and calls it using an instance of the first parameter of the method:

namespace MyExtensions
    public static class MyExtensionClass
    public extension static method WordCount, int
      Parm1, string
proc
    <method body>
end
import MyExtensions
main
record
    str, string
    x, int
proc
    x = str.WordCount()

The example below asynchronously gets the page titles from www.weather.gov and www.synergex.com.

public async method clickit, void
record
    wc, @WebClient
    uri, @Uri
    uri2, @Uri
    uri3, @Uri
proc
    listBox1.Items.Add("before");
    wc = new WebClient()
    uri = new Uri("http://www.weather.gov");
    WriteLinePageTitle(await wc.DownloadStringTaskAsync(uri))
    listBox1.Items.Add("between");
    uri2 = new Uri("http://www.synergex.com");
    WriteLinePageTitle(await wc.DownloadStringTaskAsync(uri2))
    listBox1.Items.Add("after");
endmethod

The following example declares a partial class and partial method:

namespace ns1
public partial class class1
    public static partial method meth1, void
    proc
        Console.WriteLine("meth1");
    endmethod
endclass
endnamespace

The example below returns a reference to the first parameter:

public static byref method myval, int
byref parm1, int
proc
mreturn parm1
end

Using this value, we can also define a local variable that is also a reference (by adding BYREF before DATA on a local data field):

data ivar, int, 8
byref data iref, int
iref = ns1.class1.myval(ivar)
Console.WriteLine(iref);

In this example, the return and the local variable are both references to the location of ivar. So if we changed the value of ivar to 9 and printed out iref, we’d see 9:

var = 9;
Console.WriteLine(iref);

In the example below parm1 is passed by reference, but the compiler prevents any other routines from modifying the return:

public byref readonly method meth4, @class0
    in byref parm1, @class0
proc
    mreturn parm1;
end