简体   繁体   English

如何在 C# 中创建 F# 匿名记录?

[英]How do you create F# anonymous records in C#?

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那么如果它暴露在 C# 中,那么我可以用

var someInteger = myRecord.SomeInteger;

What about the other way round, if I have an F# function, say:反过来呢,如果我有一个 F# 函数,请说:

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?并且它暴露给 C#,如何从 C# 实例化此函数的参数并调用它? I tried naively just placing a C# anonymous type there, ie.我天真地尝试在那里放置一个 C# 匿名类型,即。

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.我在该功能RFC 中注意到它说“该功能必须实现与 C# 匿名对象(来自 C# 3.0)的兼容性”,但没有具体提到以何种方式。 Is this supported?这是支持的吗?

Unfortunately, it seems to be basically impossible at this.不幸的是,这似乎基本上是不可能的。 We can use the awesome tool https://sharplab.io/ to have a look what is going on and how will the API look like.我们可以使用很棒的工具https://sharplab.io/来看看发生了什么以及 API 会是什么样子。

You can have a look at the example at: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AbEAzAzgHwFgAoDGAFwAIBbATwCUZIoATSgXkoG99KBlCNRgBJAHbkYAcxhQOlAKyV8AXxJkqAV1EB3KAEMADgB4A5HoB8lABSxmbEN14ChYidNkOzS5QEo5t6BYAOmcRcSkZEiA==你可以看一下例子在: https://sharplab.io/#v2:EYLgxg9gTgpgtADwGwBYA0AbEAzAzgHwFgAoDGAFwAIBbATwCUZIoATSgXkoG99KBlCNRgBJAHbkYAcxhQOlAKyV8AXxJkqAV1EB3KAEMADgB4A5HoB8lABSxmbEN14ChYidNkOzS5QEo5t6BYAOmcRcSkZEiA==

I have pasted following F# into it and let it compile and then decompile as C# code:我已将以下 F# 粘贴到其中并让它编译,然后反编译为 C# 代码:

let createRecord () = {| SomeInteger = 5 |}
let unwrap (record : {| SomeInteger : int |}) = record.SomeInteger

We can see that the F# compiler generated class named <>f__AnonymousType2453178905 .我们可以看到 F# 编译器生成了名为<>f__AnonymousType2453178905类。 The name is the major problem, as you can't reference it in C# :/ (AFAIK).名称是主要问题,因为您不能在 C#:/ (AFAIK) 中引用它。 Btw, it interesting that the type of SomeInteger is generic, so you can write the unwrap function generic and it will still work:顺便说一句,有趣的是SomeInteger的类型是泛型的,所以你可以编写通用的unwrap函数,它仍然可以工作:

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:这意味着:

  • I'd avoid using anonymous records in public API我会避免在公共 API 中使用匿名记录
  • If you really want to use them, you'll have to provide factory functions for them.如果你真的想使用它们,你就必须为它们提供工厂函数。
    • they can be generic in all parameters, for example let createMyRecord a = {| SomeInteger = a |}它们可以在所有参数中通用,例如let createMyRecord a = {| SomeInteger = a |} let createMyRecord a = {| SomeInteger = a |} will work well let createMyRecord a = {| SomeInteger = a |}会很好用
    • while it will be usable from C#, the seeing that the parameter should be of type <>f__AnonymousType3239938913<<A>j__TPar, <B>j__TPar, <SomeInteger>j__TPar> will not be very helpful虽然它可以从 C# 使用,但看到参数应该是<>f__AnonymousType3239938913<<A>j__TPar, <B>j__TPar, <SomeInteger>j__TPar>不会很有帮助
  • If somebody else has built the API and now you have to use, you can still create the instance using reflection如果其他人已经构建了 API,现在您必须使用,您仍然可以使用反射创建实例
    • you can get the type from a MethodInfo by calling method.GetParameters()[0].ParameterType or by Type.GetType("namespace.typename numberOfGenericArgs")您可以通过调用method.GetParameters()[0].ParameterTypeType.GetType("namespace.typename numberOfGenericArgs") 从MethodInfo获取类型
    • the type has a constructor, the properties are there in alphabetic order.该类型有一个构造函数,属性按字母顺序排列。 You can use Activator.CreateInstance(...) to call it.您可以使用Activator.CreateInstance(...)来调用它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM