Basic Concepts

Declarations

Declarations in a Fore.NET program are the constituent elements of the program. Fore.NET programs are organized using namespaces, which can contain type declarations and nested namespace declarations. Type declarations are used to describe classes, structures, interfaces, enumerations, and delegates. The kinds of members permitted in a type declaration depend on the form of the type declaration. For example, class declarations can contain declarations for constants, fields, methods, properties, events, and constructors.

A declaration describes a name in the declaration space, to which the declaration belongs. It is a compile-time error to have two or more declarations that introduce members with the same name in a declaration space. It is never possible for a declaration space to contain different kinds of members with the same name.

There are several different types of declaration spaces, as described below:

The textual order, in which names are declared, is generally of no significance. Declaration order is significant in the following cases:

//A namespace is determined in the global namespace and creates a proper domain space
Namespace A
    //Determine interface in the namespace
    Interface ITest
    End Interface;
    //Determine class in the namespace
    Class Test: ITest
    End Class;
    //Determine enumeration in the namespace
    Enum Mode
        //Determine enumeration elements
        Low, Middle, High
    End Enum;
End Namespace;

Members

Namespaces and types consist of members. The members of an entity are generally available through the use of a qualified name that starts with a reference to the entity, followed by a "." token, followed by the member name.

Members of a type are either declared in the type or inherited from the base class of the type. When a type inherits from a base class, all members of the base class, except for constructors, become members of the derived type. The declared member access level does not affect their inheritance. However, a member may not be accessible in a derived type, either because of its declared access level or because it is hidden.

Namespaces, types and methods declared outside another namespace are global namespace members.

//Interface is a namespace member
Interface ITest
    //Determine interface members that will be implemented in the class
    Function Run(ExecuteParams: Mode): Integer;
    Property Status: Integer
        Get;
    End Property Status;
End Interface;
//Class is a namespace member
Class Test1: ITest
    //Determine class members
    iResult: Integer;
    iStatus: Integer;

    Public Function Run(ExecuteParams: Mode): Integer;
    Begin
        iStatus := 0;
        //...
        Select Case ExecuteParams
            //...
            //Various variants of execution according to the input parameter value
            //...
            Case Mode.Low: iResult := 1;
            Case Mode.Middle: iResult := 2;
            Case Mode.High: iResult := 3;
        End Select;
        //...
        iStatus := 100;
        Return iResult;
    End Function;

    Public Property Status: Integer
        Get
        Begin
            Return iStatus
        End Get
    End Property;
End Class;
//Enumeration is a namespace member
Enum Mode
    //Determine enumeration elements
    Low, Middle, High
End Enum;

Member Visibility Scope

Declarations of members enable control over member access. The visibility of a member is established by the access level stated in its declaration combined with the access level of the immediately containing type, if any.

The following access levels are possible:

Depending on the context, in which a member declaration takes place, only certain access modifiers are permitted. When a member declaration does not include any access modifiers, its visibility is determined by the default declared accessibility.

Visibility Scopes

A visibility scope of a member is a set of program sections, in which access to the member is permitted. For purposes of defining the visibility scope of various program members, a member is said to be nested if it is declared within another type. Other members (that are not declared within another type) we will call top-level members. The program text is declared as program text contained in all files of source text (compilation units). Text of a type is the entire text contained between the header and the End closing structure in class, structures, interface, or enumeration declarations.

The visibility scope of a standard type (such as Object, Integer or Double) is unlimited.

The visibility scope of a top-level type T in a program P is determined as follows:

From these declarations it follows that the visibility scope of a top-level type is always at least the program, in which that type is declared.

The visibility scope of a nested member M declared in a type T within a program P is determined as follows:

From these declarations it follows that the visibility scope of a nested member is always at least the program text of the type in which the member is declared. Furthermore, the visibility scope of a member is never more inclusive than the visibility scope of the type, in which the member is declared.

On calling the M type or member, the access is checked as follows:

  1. If M is determined inside the type and the type is not accessible, the compilation error occurs.

  2. If M has a public access level, the access is permitted, or:

Member Visibility Constraints

Specific structures in the language require a type to be at least as accessible as a member or another type. A type T is said to be at least as accessible as a member or type M if the visibility scope of T is a superset of the visibility scope of M. In other words, type T is to be accessible in all contexts, in which M is accessible.

The following constraints exist:

Signatures and Overloading

Methods, instance constructors, and properties are characterized by their signatures:

Signatures enables the use of overloading of members in classes, structures, and interfaces. Overloading permits a class, structure, or interface to declare multiple members of the same kind (method, event, or constructor) with the same name, provided their signatures differ.

Note that the members declared in the same type cannot have signatures that differ only in the presence of modifiers Var and Out. Successful compilation requires some other differences.

Name Scopes

The scope of a name is the region of program text, within which it is possible to use this name without its qualification. Scopes can be nested, and an inner scope may redetermine the meaning of a name from an outer scope. The name from the outer scope is then said to be hidden, and access to the outer name is only possible by qualifying the name.

Name Hiding

Name hiding occurs when scopes of names of different program entities overlap through inheritance or nesting.

Namespace and Type Names

Several contexts in program require a namespace name or a type name to be specified. Either form of a name is written as one or more identifiers separated by points.

namespace-name:

namespace-or-type-name

type-name:

namespace-or-type-name

namespace-or-type-name:

identifier   type-argument-listopt

namespace-or-type-name   .   identifier   type-argument-listopt

Fully Qualified Names

Every namespace and type has a fully qualified name (full name), which uniquely identifies the namespace or type amongst all others. The fully qualified name of a namespace or type N is determined as follows:

Automatic Memory Control

The Fore.NET language implements automatic memory control. A developer does not need to manually select memory for objects and release it when an object is not longer used. Automatic memory control is executed by garbage collector. Object life cycle looks as follows:

  1. On creating an object a constructor is executed, memory is selected, and access is given to the object object instance.

  2. The compiler and garbage collector track object links.

  3. If an object is no longer used or not available, decomposer is automatically called for it.

  4. After the decomposer worked, the object is considered to be deleted and is not longer available.

  5. Later, the garbage collector releases memory related with this object.

The garbage collector saves information about objects and uses it to make decisions and control memory. Automatic memory control is executed on working with objects developed in application code in the Fore.NET language. In some cases forced garbage collector control may be required, this is implemented by means of the System.GC (mscorlib.dll) class methods. For example, on working with repository system objects, which kernel is developed by means of COM technology.

Public Shared Sub Main(Params: StartParams);
Var
    //...
    MB: IMetabase;
    Report: IPrxReport;
    //...
Begin
    //...
    MB := Params.Metabase;
    Report := MB.ItemById["Report"].Bind() As IPrxReport;
    //...
    //Working with report and data contained in it
    //...
    //Release object
    Report := Null;
    //Garbage collecting, memory release, which was selected for report and data
    System.GC.Collect();
    //...
    //Further working with repository and other objects
    //...
End Sub;

On working with COM objects to release them in time, use the System.Runtime.InteropServices.Marshal.ReleaseComObject method. Working with resources of the Fore language from Fore.NET may also require forced garbage collecting. The CollectFullGarbage and CollectGarbage methods are used for these purposes. For details about these methods read the Using Resources of Foresight Analytics Platform in External Applications > Garbage Collection knowledgebase article.