我可以看到,如果我创建了一个新的匿名记录,例如。
let myRecord = {| SomeInteger = 5 |}
Run Code Online (Sandbox Code Playgroud)
那么如果它暴露在C#中,我可以用
var someInteger = myRecord.SomeInteger;
Run Code Online (Sandbox Code Playgroud)
如果我有F#函数,反过来又说:
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
Run Code Online (Sandbox Code Playgroud)
而且它暴露给C#,如何从C#实例化此函数的参数并调用它?我天真地尝试只在其中放置一个C#匿名类型,即。
var unwrapped = unwrap(new { SomeInteger = 5 });
Run Code Online (Sandbox Code Playgroud)
但这没有编译。我在RFC中注意到该功能,它表示“该功能必须实现与C#匿名对象(来自C#3.0)的兼容性”,但并未以哪种方式具体提及。支持吗?
不幸的是,这似乎基本上是不可能的。我们可以使用https://sharplab.io/来看看发生了什么以及 API 是什么样子。
我将以下 F# 粘贴到其中,让它编译,然后反编译为 C# 代码:
let createRecord () = {| SomeInteger = 5 |}
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger
Run Code Online (Sandbox Code Playgroud)
我们可以看到 F# 编译器生成的类名为<>f__AnonymousType2453178905. 名称是主要问题,因为您无法在 C# 中引用它:/ (AFAIK)。顺便说一句,有趣的是 的类型SomeInteger是通用的,因此您可以编写unwrap通用函数,它仍然可以工作:
let unwrap<'a> (record : {| SomeInteger : 'a |}) = record.SomeInteger
Run Code Online (Sandbox Code Playgroud)
翻译后的函数看起来像这样
public static <>f__AnonymousType2453178905<int> createRecord()
{
return new <>f__AnonymousType2453178905<int>(5);
}
public static int unwrap(<>f__AnonymousType2453178905<int> record)
{
return record.SomeInteger;
}
Run Code Online (Sandbox Code Playgroud)
这意味着:
let createMyRecord a = {| SomeInteger = a |}可以很好地工作<>f__AnonymousType3239938913<<A>j__TPar, <B>j__TPar, <SomeInteger>j__TPar>不会有太大帮助MethodInfo您可以通过调用method.GetParameters()[0].ParameterType或通过Type.GetType("namespace.typenamenumberOfGenericArgs来获取类型”)Activator.CreateInstance(...)它来调用它。| 归档时间: |
|
| 查看次数: |
239 次 |
| 最近记录: |