Implementing Oberon Modules in C#
The C# language unfortunately does not provide a module feature. Nevertheless, the access modifier internal makes implementing Oberon-style module semantics quite straightforward. On the binary level an Oberon module comes very close to a .NET assembly. In code, the C# modifier internal limits member accessibility to a single assembly, so we can use it to designate module wide visibility.
Module members that are marked as exported in Oberon become public in C#. Further, for better readability the MODULE keyword can be emulated with a C# namespace keyword - as long as every assembly is assigned one unique namespace. To import another module, reference its assembly and insert a using statement for the corresponding namespace.
Here's an example of a module M in Component Pascal. Note that comments are also in Component Pascal syntax. All procedure and method bodies are empty for the sake of brevity.
(* M.odc *)
MODULE M;
IMPORT Q; (* imported module *)
TYPE
T* = POINTER TO RECORD END; (* exported class *)
U = POINTER TO RECORD END;
VAR
i*: INTEGER; (* exported module variable *)
j: INTEGER;
PROCEDURE (t: T) A*, NEW; BEGIN END A; (* exported method *)
PROCEDURE (t: T) B, NEW; BEGIN END B;
PROCEDURE F* BEGIN END F; (* exported procedure *)
PROCEDURE G BEGIN END G;
BEGIN
(* module initialization ... *)
END M.
The same module could be implemented in C# as follows
// M.cs
namespace M {
using Q; // imported module
public sealed class T { // exported class
public void A () {} // exported method
internal void B () {}
}
sealed class U {} // internal by default
public sealed class M {
M () {} // private by default
public static int i; // exported module variable
internal static int j;
public static void F () {} // exported procedure
internal static void G () {}
static M () {
// module initialization ...
}
}
}
Now look at the interface definition generated out of the compiled Component Pascal module
DEFINITION M;
TYPE
T = POINTER TO RECORD
(t: T) A, NEW
END;
VAR
i: INTEGER;
PROCEDURE F;
END M.
And the public interface of the compiled C# code as generated by Lutz Röder's Reflector
namespace M {
public sealed class T {
public T();
public void A();
}
public sealed class M {
public static int i;
public static void F();
}
}
To sum things up: Implementing modules is possible and quite easy thanks to Anders Hejlsberg who - familiar with units, Delphi's module feature - presumably sneaked the internal modifier into C#.
|