Consume case-sensitive C# library with Oxygene

Hi there!

A third-party-.net-library, written in C#, offers some class “ExampleIOStuff”.

Despite an error message, it took me several hours to realize, why i am not able to create an instance of this class:
(E672) Type "ExampleIoStuff" has no accessible constructors

Notice the difference? Me neither :wink:

Several classes of the library have an accompanying struct, with different case in the names - classes “IO”, structs “Io”.

Is there a way to consume this library from Oxygene without refactoring the external code?

Cheers

this should work if you encase the name with Guillemet:, eg:

x := new «ExampleIOStuff»;.

between the « and », any character will be treated as part of the identifier (ie you could have socking, punctuation, you name it), and it should enforce/preserve the case too.

As a side note, I’m wondering if two classes with “the same” name should emit an “ambiguous name” error rather than picking one at random as it does now. @ck?

Thanks, this worked… Funny enough: Now it works, even if i remove the «» again…

Yesterday “Go To Type Definition” brought me to the record-interface (from metadata). Every single time! Now it jumps to the class-interface (from metadata).
It wasn’t until the examination of the library-assembly with dotPeek that I could see what the problem was.

All the more reason I think this must become an error. It might be literally random which one gets picked…

(FTR, exposing public APIs that only differ in case is n to CLS-compliant).

Thanks, logged as bugs://85449

Curious, in this testcase in just created it picks the right one for each…

namespace ConsoleApplication70;

type
  Program = class
  public

    class method Main(args: array of String): Int32;
    begin
      // add your own code here
      writeLn('The magic happens here.');
      
      var f1 := new Foo;
      f1.Bar;

      var f2 := new foo;
      f2.Bar;
    end;

  end;
  
  «Foo» = public class
  public
    method Bar;
    begin
      writeLn("upper");
    end;
  end;

  «foo» = public class
  public
    method Bar;
    begin
      writeLn("lower");
    end;
  end;

end.

but if the same comes from externally (ie C#), I get


      var b1 := new ClassLibrary.Bar;
      b1.Bar;

      var b2 := new ClassLibrary.bar; // GETS AUTO_FIX -  W0 Case for identifier "bar" does not match original case "Bar"
      b2.Bar;

it it picks one, and even force-corrects it to that.

Broken down C#-library (MS, not RO!) to the bare minimum:

using System;

namespace TestCase
{
    public struct ExampleIoStuff 
    {
    }

    public class ExampleIOStuff 
    {
        public ExampleIOStuff(string someValue)
        {
        }
    }
}

Trying to use it from an Oxygene project

var x := new «TestCase.ExampleIOStuff»('foo');

results in…

Fehler|(E672) Type "TestCase.ExampleIoStuff" has no accessible constructors
Warnung|(W0) Case for identifier "ExampleIOStuff" does not match original case "ExampleIoStuff"

Doesn’t work with or without the “«»”

Edit:

lol

Adding the namespace “TestCase” to “uses” and removing the namespace from the statement resolves the issue.

var x := new ExampleIOStuff('foo');  // this works now
1 Like

bugs://85449 got closed with status fixed.