Reputation: 371
I can see that if I create a new anonymous record, eg.
let myRecord = {| SomeInteger = 5 |}
then if it's exposed to C# then I can dot into it with
var someInteger = myRecord.SomeInteger;
What about the other way round, if I have an F# function, say:
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
and it's exposed to C#, how can I instantiate an argument for this function from C# and call it? I tried naively just placing a C# anonymous type there, ie.
var unwrapped = unwrap(new { SomeInteger = 5 });
but this didn't compile. I note in the RFC for the feature it's said that "The feature must achieve compatibility with C# anonymous objects (from C# 3.0)" but it's not specifically mentioned in which ways. Is this supported?
Upvotes: 12
Views: 1600
Reputation: 510
Unfortunately, it seems to be basically impossible. We can use https://sharplab.io/ to have a look what is going on and how will the API look like.
You can have a look at the example at: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AbEAzAzgHwFgAoDGAFwAIBbATwCUZIoATSgXkoG99KBlCNRgBJAHbkYAcxhQOlAKyV8AXxJkqAV1EB3KAEMADgB4A5HoB8lABSxmbEN14ChYidNkOzS5QEo5t6BYAOmcRcSkZEiA==
I have pasted following F# into it, let it compile and then decompile as C# code:
let createRecord () = {| SomeInteger = 5 |}
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
We can see that the F# compiler generated class named <>f__AnonymousType2453178905
. The name is the major problem, as you can't reference it in C# :/ (AFAIK). Btw, it is interesting that the type of SomeInteger
is generic, so you can write the unwrap
function generic and it will still work:
let unwrap<'a> (record : {| SomeInteger : 'a |}) = record.SomeInteger
The translated function look like this
public static <>f__AnonymousType2453178905<int> createRecord()
{
return new <>f__AnonymousType2453178905<int>(5);
}
public static int unwrap(<>f__AnonymousType2453178905<int> record)
{
return record.SomeInteger;
}
That means:
let createMyRecord a = {| SomeInteger = a |}
will work well<>f__AnonymousType3239938913<<A>j__TPar, <B>j__TPar, <SomeInteger>j__TPar>
will not be very helpfulMethodInfo
by calling method.GetParameters()[0].ParameterType
or by Type.GetType("namespace.typename
numberOfGenericArgs")Activator.CreateInstance(...)
to call it.Upvotes: 2