Maslow
Maslow

Reputation: 18746

Why does a StaticallyResolvedTypeParameter method call compile when it fails at run-time?

I've just written a simple method that C# can see but calling it (even with valid arguments) throws up at run-time.

example that fails at runtime:

F#:

namespace Library1
type Class1() = 
  member __.Foo = "F#"
module MyModule = 
  // fails at run-time
  let inline fOnly (x:^a) : string = (^a:(member Foo: _) x)
  // works from C# and F# so I know it's not a problem with my stp
  let testFOnly () = fOnly (Class1())

C# consumer:

namespace ConsoleApplication1
  {
    class Program
    {
      var class1 = new Library1.Class1();
      // NotSupportedException
      var result = Library1.MyModule.fOnly(class1);
      Console.ReadLine();    
    }
  }

Why does this compile, then fail at run-time? Am I doing something wrong or should I just assume any attempt to call an stp method from C# will always fail? Should I then attempt to hide them from C#?

Upvotes: 0

Views: 71

Answers (2)

cloudRoutine
cloudRoutine

Reputation: 370

The code in the example is wrong

Class1 has the member Foo not X and it fails to compile

-------------- After Question Edit ------------

You can use ILSpy to see the decompiled code and the source of the error

Decompiled C# -

namespace Library1
{
    [CompilationMapping(SourceConstructFlags.Module)]
    public static class MyModule
    {
        public static string fOnly<a>(a x)
        {
            "Dynamic invocation of get_Foo is not supported";
            throw new NotSupportedException();
        }

        public static string testFOnly()
        {
            Class1 @class = new Class1();
            return "F#";
        }
    }
}

But you can see from the code that this will work

static void Main ( string [ ] args )
{
  Console.WriteLine( Library1.MyModule.testFOnly()) ;
  Console.ReadLine();  
}

There's also no reason to make this a function call let testFOnly () = fOnly (Class1()) instead of a regular binding since it's targeting an immutable property of the class.

i.e. let testFOnly = Class1() |> fOnly

Upvotes: 2

John Palmer
John Palmer

Reputation: 25516

The use of inline in F# doesn't actually produce a function in the output assembly.

The function is encoded in some metadata that only the F# compiler can read and then insert inline.

As a result, you cannot call inline functions from C#

Upvotes: 2

Related Questions