例如,我可以看到是否创建了一个新的匿名记录。
let myRecord = {| SomeInteger = 5 |}
然后,如果它暴露在C#中,那么我可以用
var someInteger = myRecord.SomeInteger;
反之,如果我有F#函数,说:
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
并且它已经暴露在C#中,如何从C#实例化此函数的参数并调用它?我天真地尝试只在其中放置一个C#匿名类型,即。
var unwrapped = unwrap(new { SomeInteger = 5 });
但是没有编译。我在RFC for the feature中注意到说“该功能必须实现与C#匿名对象(从C#3.0起)的兼容性” ,但没有以哪种方式具体提及。支持吗?
答案 0 :(得分:1)
不幸的是,这似乎基本上是不可能的。我们可以使用很棒的工具https://sharplab.io/来看看发生了什么以及API的外观。
我已将以下F#粘贴到其中,并使其进行编译,然后反编译为C#代码:
let createRecord () = {| SomeInteger = 5 |}
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
我们可以看到F#编译器生成了名为<>f__AnonymousType2453178905
的类。名称是主要问题,因为您无法在C#:/(AFAIK)中引用它。顺便说一句,有趣的是SomeInteger
的类型是泛型的,因此您可以编写unwrap
函数的泛型,它仍然可以工作:
let unwrap<'a> (record : {| SomeInteger : 'a |}) = record.SomeInteger
翻译后的函数如下
public static <>f__AnonymousType2453178905<int> createRecord()
{
return new <>f__AnonymousType2453178905<int>(5);
}
public static int unwrap(<>f__AnonymousType2453178905<int> record)
{
return record.SomeInteger;
}
这意味着:
let createMyRecord a = {| SomeInteger = a |}
会很好地工作<>f__AnonymousType3239938913<<A>j__TPar, <B>j__TPar, <SomeInteger>j__TPar>
类型的提示MethodInfo
或method.GetParameters()[0].ParameterType
numberOfGenericArgs“从Type.GetType("namespace.typename
获取类型Activator.CreateInstance(...)
来调用它。