Regardons le code, généré par F# pour une fonction simple :
let map_add valueToAdd xs =
xs |> Seq.map (fun x -> x + valueToAdd)
Le code généré pour l'expression lambda (instance de valeur fonctionnelle F#) ressemblera à ceci :
[Serializable]
internal class map_add@3 : FSharpFunc {
public int valueToAdd;
internal map_add@3(int valueToAdd) { this.valueToAdd = valueToAdd; }
public override int Invoke(int x) { return (x + this.valueToAdd); }
}
Et regardons presque le même code C# :
using System.Collections.Generic;
using System.Linq;
static class Program {
static IEnumerable SelectAdd(IEnumerable source, int valueToAdd) {
return source.Select(x => x + valueToAdd);
}
}
Et le code généré pour l'expression lambda en C# :
[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
public int valueToAdd;
public int b__0(int x) { return (x + this.valueToAdd); }
}
J'ai donc quelques questions :
- Pourquoi la classe générée par F# n'est-elle pas marquée comme
sealed
? - Pourquoi la classe générée par F# contient-elle des champs public alors que F# n'autorise pas les fermetures mutables ?
- Pourquoi la classe générée par F# a-t-elle un constructeur ? Elle pourrait être parfaitement initialisée avec les champs publics...
- Pourquoi la classe générée par C# n'est-elle pas marquée comme
[Serializable]
? De plus, les classes générées pour les expressions de séquence F# deviennent également[Serializable]
et les classes pour les itérateurs C# ne le deviennent pas.