c# - expressions - ventajas expresiones lambda
Generación de código de expresiones C#y F#lambda (2)
Miremos el código, generado por F # para la función simple:
let map_add valueToAdd xs =
xs |> Seq.map (fun x -> x + valueToAdd)
El código generado para la expresión lambda (instancia de valor funcional F #) se verá así:
[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); }
}
Y mira casi el mismo código 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);
}
}
Y el código generado para la expresión lambda de C #:
[CompilerGenerated]
private sealed class <>c__DisplayClass1 {
public int valueToAdd;
public int <SelectAdd>b__0(int x) { return (x + this.valueToAdd); }
}
Entonces tengo algunas preguntas:
- ¿Por qué la clase generada por F # no está marcada como
sealed
? - ¿Por qué la clase generada por F # contiene campos públicos ya que F # no permite cierres mutables?
- ¿Por qué la clase generada F # tiene un constructor? Puede estar perfectamente inicializado con los campos públicos ...
- ¿Por qué la clase generada por C # no está marcada como
[Serializable]
? También las clases generadas para las expresiones de secuencia F # también se convirtieron en[Serializable]
y las clases para los iteradores C # no.
¿Por qué la clase generada por F # no está marcada como sellada?
Porque el compilador no (esto es al final una opción de generación de código.
¿Por qué la clase generada por F # contiene campos públicos ya que F # no permite cierres mutables?
Debería poder obtener una referencia a una instancia para modificarla. Pero no puedes, entonces ser modificable no importa. Y probablemente esto evite la necesidad de un caso especial en el que se capture un mutable en un cierre.
¿Por qué la clase generada F # tiene un constructor? Puede estar perfectamente inicializado con los campos públicos ...
De nuevo, elección de generación de código.
¿Por qué la clase generada por C # no está marcada como [Serializable]? También las clases generadas para las expresiones de secuencia F # también se convirtieron en [Serializable] y las clases para los iteradores C # no.
Más opciones de generación de código.
Ninguna de estas opciones es visible por el desarrollador (es decir, no hace ninguna diferencia en el código del cliente) realmente no hace ninguna diferencia.
Dado que son generados por el compilador, los problemas del campo sellado / público son un poco discutibles (no debería verlo nunca más que a través de herramientas de depuración), ¿cómo lo estaría subclasificando o mutando, excepto al recorrer el compilador? Si tiene ese nivel de acceso de depuración puede mutarlo de todos modos (a través de la reflexión).
Para C #, debe ser un campo para permitir cierto uso de ref
/ out
, y para permitir el uso correcto con las estructuras mutables capturadas (sí, mal, lo sabemos). Supongo que F # es similar aquí (¿puedes mutar un miembro sub- [sub- [sub -]] del valor capturado?). Sin embargo, los miembros probablemente podrían ser internos.
Re [Serialziable]
; ¿Por qué algo que sustenta un cierre puede ser serializable? Los delegados hacen candidatos de serialización extremadamente pobres. Tal vez la naturaleza de F # significa que es más adecuado para persistir una operación (flujo medio) en el disco, pero en general, no lo recomendaría. No esperaría que estos objetos (iteradores y clases de captura) se puedan serializar.