让我们看一下 F# 为简单函数生成的代码:
let map_add valueToAdd xs =
xs |> Seq.map (fun x -> x + valueToAdd)
生成的 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); }
}
查看几乎相同的 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);
}
}
以及 C# lambda 表达式的生成代码:
[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
public int valueToAdd;
public int <SelectAdd>b__0(int x) { return (x + this.valueToAdd); }
}
所以我有一些问题:
- 为什么 F# 生成的类没有标记为
sealed
?
- 为什么 F# 生成的类包含public字段,因为 F# 不允许可变闭包?
- 为什么 F# 生成的类有构造函数?它可以用公共字段完美地初始化......
- 为什么 C# 生成的类没有标记为
[Serializable]
?为 F# 序列表达式生成的类也变成了[Serializable]
而 C# 迭代器的类则不然。
由于它们是编译器生成的,因此密封/公共字段问题有点没有实际意义 - 除了通过调试工具之外,您不应该看到它 - 除了绕过编译器之外,您将如何子类化它或改变它?如果你有that您可以改变它的调试访问级别anyway(通过反射)。
对于 C# 来说,它需要是field允许某些ref
/ out
用法,并允许正确使用捕获的可变结构(是的,邪恶,我们知道)。我假设 F# 在这里是类似的(你可以改变捕获值的 sub-[sub-[sub-]] 成员吗?)。不过,这些成员可能是内部成员。
Re [Serialziable]
;为什么支撑闭包的东西是可序列化的?代表们是极差的连载候选人。也许 F# 的本质意味着它更适合将操作(中流)持久保存到磁盘 - 但总的来说,我不推荐它。我不期望这些对象(迭代器和捕获类)是可序列化的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)