简体   繁体   English

C#和F#lambda表达式代码生成

[英]C# and F# lambda expressions code generation

Let's look at the code, generated by F# for simple function: 让我们看一下F#为简单函数生成的代码:

let map_add valueToAdd xs =
    xs |> Seq.map (fun x -> x + valueToAdd)

The generated code for lambda expression (instance of F# functional value) will looks like this: 生成的lambda表达式代码(F#功能值的实例)如下所示:

[Serializable]
internal class map_add@3 : FSharpFunc<int, int> {
    public int valueToAdd;
    internal map_add@3(int valueToAdd) { this.valueToAdd = valueToAdd; }
    public override int Invoke(int x)  { return (x + this.valueToAdd); }
}

And look at nearly the same C# code: 看看几乎相同的C#代码:

using System.Collections.Generic;
using System.Linq;

static class Program {
    static IEnumerable<int> SelectAdd(IEnumerable<int> source, int valueToAdd) {
        return source.Select(x => x + valueToAdd);
    }
}

And the generated code for the C# lambda expression: 并为C#lambda表达式生成代码:

[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
    public int valueToAdd;
    public int <SelectAdd>b__0(int x) { return (x + this.valueToAdd); }
}

So I have some questions: 所以我有一些问题:

  • Why is F#-generated class not marked as sealed ? 为什么F#生成的类没有标记为sealed
  • Why does F#-generated class contain public fields since F# doesn't allow mutable closures? 为什么F#生成的类包含公共字段,因为F#不允许可变闭包?
  • Why does F# generated class have a constructor? 为什么F#生成的类有一个构造函数? It may be perfectly initialized with the public fields... 它可以用公共领域完美地初始化......
  • Why is C#-generated class not marked as [Serializable] ? 为什么C#生成的类没有标记为[Serializable] Also classes generated for F# sequence expressions also became [Serializable] and classes for C# iterators do not. 此外,为F#序列表达式生成的类也变为[Serializable] ,而C#迭代器的类则不会。

Since they are compiler-generated, the sealed / public field issues are a bit moot - you shouldn't ever see it except via debug tools - how would you be subclassing it or mutating it, except by stepping around the compiler? 由于它们是编译器生成的,密封/公共字段问题有点没有意义 - 除了通过调试工具之外你不应该看到它 - 除了通过单独编译器之外,你将如何对它进行子类化或变异? If you have that level of debug access you can mutate it anyway (via reflection). 如果您具有级别的调试访问权限,则无论如何都可以对其进行变更 (通过反射)。

For C# it needs top be a field to allow certain ref / out usage, and to allow correct usage with captured mutable structs (yes, evil, we know). 对于C#,它需要一个字段来允许某些ref / out使用,并允许正确使用捕获的可变结构(是的,邪恶,我们知道)。 I assume F# is similar here (can you mutate a sub-[sub-[sub-]]member of the captured value?). 我假设F#在这里类似(你可以改变捕获值的子[sub- [sub - ]]成员吗?)。 The members could probably be internal, though. 但成员可能是内部成员。

Re [Serialziable] ; Re [Serialziable] ; why would something that underpins a closure be serializable? 为什么支持闭包的东西可以序列化? Delegates make extremely poor serialization candidates. 代表们制作了极差的序列化候选人。 Maybe the nature of F# means that it is better suited to persisting an operation (mid-flow) to disk - but in general, I wouldn't recommend it. 也许F#的本质意味着它更适合于将操作(中间流)持久化到磁盘 - 但总的来说,我不推荐它。 I would have no expectation of these objects (iterators and capture-classes) being serialzable. 我不希望这些对象(迭代器和捕获类)是可序列化的。

Why is F#-generated class not marked as sealed? 为什么F#生成的类没有标记为密封?

Because the compiler doesn't (this is in the end a code generation choice. 因为编译器没有(这到底是代码生成的选择。

Why does F#-generated class contain public fields since F# doesn't allow mutable closures? 为什么F#生成的类包含公共字段,因为F#不允许可变闭包?

You would need to be able to get to a reference to an instance to modify it. 您需要能够获得对实例的引用以进行修改。 But you can't, so being modifiable doesn't matter. 但你不能,所以可修改无所谓。 And likely this avoids needing to special case where a mutable is captured in a closure. 并且这可能避免需要在闭包中捕获mutable的特殊情况。

Why does F# generated class have a constructor? 为什么F#生成的类有一个构造函数? It may be perfectly initialized with the public fields... 它可以用公共领域完美地初始化......

Again code generation choice. 再次代码生成选择。

Why is C#-generated class not marked as [Serializable]? 为什么C#生成的类没有标记为[Serializable]? Also classes generated for F# sequence expressions also became [Serializable] and classes for C# iterators do not. 此外,为F#序列表达式生成的类也变为[Serializable],而C#迭代器的类则不会。

More code generation choices. 更多代码生成选择。

None of these choices is developer visible (ie make no difference to client code) it really makes no difference. 这些选择都不是开发人员可见的(即对客户端代码没有任何影响),它确实没有任何区别。

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

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