25 votes

Génération de code des expressions lambda en C# et F#

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.

4voto

Marc Gravell Points 482669

Puisqu'ils sont générés par le compilateur, les problèmes de champ scellé / public sont un peu caduques - vous ne devriez jamais le voir sauf via des outils de débogage - comment le sous-classeriez-vous ou le muteriez-vous, à moins de contourner le compilateur? Si vous avez ce niveau d'accès au débogage, vous pouvez de toute façon le muter (via la réflexion).

Pour C#, il doit s'agir d'un champ pour permettre certains usages ref / out, et permettre un usage correct avec des structs mutables capturées (oui, malveillantes, nous le savons). J'imagine que F# est similaire ici (pouvez-vous muter un sous-[sous-[sous-]]membre de la valeur capturée?). Les membres pourraient probablement être internes, cependant.

Concernant [Serializable]; pourquoi quelque chose qui sous-tend une fermeture serait-il sérialisable? Les délégués font de très mauvais candidats à la sérialisation. Peut-être que la nature de F# signifie qu'il est mieux adapté à persister une opération (en cours) sur disque - mais en général, je ne le recommanderais pas. Je n'aurais aucune attente à ce que ces objets (itérateurs et classes de capture) soient sérialisables.

4voto

Richard Points 54016

Pourquoi la classe générée par F# n'est-elle pas marquée comme scellée?

Parce que le compilateur ne le fait pas (c'est en fin de compte un choix de génération de code).

Pourquoi la classe générée par F# contient-elle des champs publics alors que F# n'autorise pas les fermetures mutables?

Il faudrait pouvoir accéder à une référence à une instance pour la modifier. Mais vous ne pouvez pas, donc le fait d'être modifiable n'a pas d'importance. Et probablement cela évite d'avoir à traiter spécifiquement les cas où un mutable est capturé dans une fermeture.

Pourquoi la classe générée par F# a-t-elle un constructeur? Elle peut être parfaitement initialisée avec les champs publics...

Encore une fois, c'est un choix de génération de code.

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équences F# deviennent également [Serializable] et les classes pour les itérateurs C# ne le font pas.

Davantage de choix de génération de code.

Aucun de ces choix n'est visible pour le développeur (c'est-à-dire qu'ils ne font aucune différence pour le code client), cela n'a vraiment aucune importance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X