Type "String" has no accessible constructors

I have this simple macOS Island console app (C#):

    static class Program
    {
        public static int indentLevel = 0;
        
        public static Int32 Main(string[] args)
        {
            Console.WriteLine("The magic happens here.");
            return 0;
        }
        
        public static string Indent()
        {
            if (indentLevel == 0)
            {
                return "";
            }
            else
            {
                return new string(' ', indentLevel*3);
            }
        }
    }

The compiler is failing to build with the error message:

Program.cs, line 21 — (E672) Type “String” has no accessible constructors

I don’t understand the error for two reasons:

  1. The docs say there is a matching constructor:
constructor (Char, Int32)

Creates a string with aChar repeated aCount times.

OxygeneC#SwiftJavaMercury
 

constructor(aChar: Char; aCount: Int32)
Parameters:

aChar:
aCount:
  1. I have the exact same line of code in another macOS Island C# RTL project and don’t get the error.

What am I missing here? This is a brand new project. I restarted my Mac.

is this with RemObjects.Elements.RTL in the4 uses clause/scope, or not? Because there’s two different String types, Island and Elements RTL.

There’s no using clause above the program class. The project references both island and RTL. How do I tell the compiler which string type to use?

Check the Default Uses setting in your project, and/or do Peek at Definition on String to see what full type name it shows.

Hovering over the return type for the Indent() method, it’s using RemObjects.Elements.System.String.

However, hovering over new string at the end of the method it shows:

If I’m interpreting the project settings correctly, it’s using RemObjects.Elements.RTL by default:

Which is the same as the other project. Curious.

Looking at the string docs for IslandRTL versus ElementsRTL I’m guessing the project is using IslandRTL which doesn’t look like the are any overridable constructors. Is that right?

I’m confused why there are two RTL libraries. Is the ElementsRTL library more feature-rich than the IslandRTL? If so, can you use ElementsRTL on Island?

Ah I see a difference between the two projects.

The simple app described above that’s not working:

Screenshot 2020-07-06 at 23.23.18

and the larger app that is working:

Screenshot 2020-07-06 at 23.23.55

The Elements reference is missing. This is weird because if you create a new project like so:

and check Elements RTL, it doesn’t seem to reference Elements.

Shouldn’t Elements be added automatically when a new project is created if the “Use Elements” check box is ticked?

This is using the latest preview build 2529.

I was as confused before.

My understanding is:

rtl namespace represents the fundamental “raw” RTL at the OS level such as Win32 APIs and associated data types, macros, constants and structures.

IslandRTL (represented as RemObjects.Elements.System) is the RTL for Island platform that works on native Windows, MAC, Linux etc. It is the RTL for the Island platform, and one ABSTRACTION level higher than RTL

Element RTL (current version 2, ie RTL 2) is one ABSTRACT level higher than IslandRTL, such that unifies the interfaces on Island, .NET, and Java. It is the RTL for all RemObjects Element Languages

So in terms of “platform abstraction” level, RTL < IslandRTL < RTL2

@mh please correct if any inaccuracies or mistakes

I see. I guess I always want to use RTL2 then?

I’m wondering if this is a bug with 2529 Fire in that Elements RTL isn’t automatically added to a new project if the checkbox for it is checked when creating a new project?

String is sealed, so there’s nothing to override, ever.

All the major “non-native” platforms come with their own rich OOP APIs to be usable. the .NET Framework, The Java SDK, the Cocoa/AppKit/UUKit frameworks. Island is low-level and (aside from macOS/iOS, where it can access Cocoa) there are no existing standard OOP paradigms present (eg Win32 API, or Linux libc). SO Island has Island RTL to provide a common OOP layer of functionality, provide Object, String, etc.

All these platforms are usable as is, with the vendor APIs (and Island RTL), and without any additional libraries…

Elements RTL is an optional extra library that provides an abstraction layer and gives you common functionality with identical AP:Is across all platforms — if you so desire. The same String class API. The same List and Dictionary — whether you work on .NET, Java, Cocoa or Island. This is so you dont have to worry about the NSArray on Cocoa vs System.Collections.Generic.List on .NET, or NSXMLDocument vs XmlDocument, etc. A common set of APIs for base functionality that work on all platforms.

You can use it from Island, yes. And while it is a great general purpose API (I use it for all my projects(, even single-platform ones), it’s main goal is to provide a consistent API for multi-platform projects.

Yes, that checkbook adds Elements RTL to the project and its namespace, RemObjects.Elements.RTL to the default uses class. If you create a project like this and declare

string x;

or even

var x = "Hello",

then x will be typed as a RemObjects.Elements.RTL.String.

I am not sure about that. My experience with Island/Windows development is to reference Elements.RTL first, then IslandRTL

uses
  RemObjects.Elements.RTL,
  RemObjects.Elements.System

The reason for to doing this is:

  • Some native platform specific methods are not available with Elements.RTL, for example, String.FromAnsiChars
  • Elements.RTL contains some useful extension methods for Island RTL classes, for example, List.JoinedString.
  • Referencing Elements.RTL first, then IslandRTL, will make my code primarily use IslandRTL classes + extension methods defined in Elements.RTL

Of course, I do this only because I care “intra”-Island native interoperability (like native Windows/MacOS/Linux, thanks to Island’s LLVM backend). I don’t care much about the cross-platform interoperability among Island/.NET/Java/Coocoa. Hence I only use Elements.RTL to augment IslandRTL., while using IslandRTL as primary - which is achieved by the order of referencing Elements.RTL first, then IslandRTL afterwards.

Note that both String “types” are the same at runtime, and you can seamlessly and toll-free cast between them; they merely provide different APIs.

RemObjects.Elements.System.String is the actual string type as implemented in Island RTL. It’s APIs are sp[ecific to Island, but modeled largely after .NET. But it’s API will be incompatible with Cocoa and Java Strings (and less so, but still, with .NET).

RemObjects.Elements.RTL.String is the idealized “cross-platform” API we envision for strings, regardless of platform, and it looks the same omg all platforms. I’d be open to feature request if important APIs are missing or you think should be exposed — as long as these APIs are sensible on all target platforms.

You can always “down-cast” a RemObjects.Elements.RTL.String to the native string, if you need to call an API thats on native but not in Elements RTL. You can also seamlessly assign native strings to RemObjects.Elements.RTL.String, and vice versa or, e.g. for tom use the native .ctor ebvewn when otherwise using Elements RTL, eg>:

using RemObjects.Elements.RTL.

string foo; // typed as RemObjects.Elements.RTL.String
foo = new RemObjects.Elements.System.String(<paramters for a ctor not exposed in ElemengtsRTL>);
foo.ToUnicodeCodePoints; // call an Elements RTL API
(foo as RemObjects.Elements.System.String).Whatever // call an Island String API

@mh thank u for the heads up. Good to know the trick.

For users like me who primarily use Island (and love it), it would be more convenient that referencing RemObjects.Elements.System will automatically introduce those extension methods defined in RemObjects.Elements.RTL, rather than explicitly down/up casting back and forth.

But I guess I am happy with the way it is, i.e., referencing both RemObjects.Elements.RTL and RemObjects.Elements.System, with the specific order.

Happy top hear!

Good idea. The idea behind only showing the mapped methods is that of your coding cross-platform, being both will be confusing, and you easily end up writing platform-specific code again. But for single-platform use, I could envision an option where mapped types extend the original, rather than hide it.

I’ll bring this up with the compiler team for what we can do here — maybe a per-project compile option?

Thanks, logged as bugs://84631

That said, this remains:

ideally, id make the Element RTLs as well-rounded as we can so you never need to drop down to the native types (except maybe for really corner-case stuff).

Feedback appreciated as to what is missing — I as looking at island RTL’sstirng for may above code example, and couldn’t really find any method it had (except maybe the extra .ctors) that Elements RTL doesn’t already also expose…

So please try putting Elements RTL int the closest scope and let me know what you actually miss when you do!

Hi marc, thank you for your attention. At least, the following code won’t compile, complaining String.FromPAnsiChars and String.ToAnsiChars are missing

namespace ConsoleApplication;

uses 
	RemObjects.Elements.RTL
    //,RemObjects.Elements.System
	;

type
  Program = class
  public

    class method Main(args: array of String): Int32;
    begin
      // add your own code here
      writeLn('The magic happens here.');
      var str1: String := 'test';
      var str2: String := String.FromPAnsiChars(@str1.ToAnsiChars(true)[0]);
      writeLn(str2);
      readLn();
    end;

  end;

end.

A per-project compile option would be GREAT, so no need to down/up cast back and forth.

I guess this new compile option - whenever it comes true, is going to be a Island-specific compile option, for merging Elements.RTL with IslandRTL?

it could probably work for any platform.