Me encontré con un código que decía
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Ahora estoy algo familiarizado con las expresiones Lambda. Simplemente no he visto que lo use de esta manera.
¿Cuál sería la diferencia entre la declaración anterior y
public int MaxHealth = x ? y:z;
Respuestas:
Lo que estás viendo es un miembro con cuerpo de expresión, no una expresión lambda.
Cuando el compilador encuentra un miembro de propiedad con cuerpo de expresión , esencialmente lo convierte en un captador como este:
(Puede verificar esto usted mismo bombeando el código a una herramienta llamada TryRoslyn ).
Los miembros con cuerpo de expresión, como la mayoría de las características de C # 6, son solo azúcar sintáctica . Esto significa que no proporcionan una funcionalidad que de otro modo no se podría lograr a través de las funciones existentes. En cambio, estas nuevas características permiten utilizar una sintaxis más expresiva y sucinta
Como puede ver, los miembros con cuerpo de expresión tienen un puñado de atajos que hacen que los miembros de propiedad sean más compactos:
return
declaración porque el compilador puede inferir que desea devolver el resultado de la expresiónget
palabra clave porque está implícita en el uso de la sintaxis de miembro con cuerpo de expresión.He puesto el último punto en negrita porque es relevante para su pregunta real, que responderé ahora.
La diferencia entre...
Y...
Es lo mismo que la diferencia entre ...
Y...
Lo cual, si comprende las propiedades, debería ser obvio.
Sin embargo, para ser claros: la primera lista es una propiedad con un captador debajo del capó que se llamará cada vez que acceda a ella. La segunda lista es un campo con un inicializador de campo, cuya expresión solo se evalúa una vez, cuando se instancia el tipo.
Esta diferencia en la sintaxis es en realidad bastante sutil y puede conducir a un "problema" que describe Bill Wagner en una publicación titulada "AC # 6 gotcha: Initialization vs. Expression Bodied Members" .
Mientras que los miembros de expresión lambda cuerpo son expresión- como , que son no las expresiones lambda. La diferencia fundamental es que una expresión lambda da como resultado una instancia delegada o un árbol de expresión. Los miembros con cuerpo de expresión son solo una directiva para que el compilador genere una propiedad detrás de escena. La similitud (más o menos) comienza y termina con la flecha (
=>
).También agregaré que los miembros con cuerpo de expresión no se limitan a los miembros de la propiedad. Trabajan en todos estos miembros:
Agregado en C # 7.0
Sin embargo, no trabajan en estos miembros:
fuente
Ok ... Hice un comentario de que eran diferentes pero no podía explicar exactamente cómo, pero ahora lo sé.
no es lo mismo que
Aquí está la diferencia ...
Cuando usa el inicializador automático, la propiedad crea la instancia de valor y usa ese valor de forma persistente. En la publicación anterior hay un enlace roto a Bill Wagner, que explica esto bien, y busqué el enlace correcto para entenderlo yo mismo.
En mi situación, mi propiedad inicializó automáticamente un comando en un ViewModel para una Vista. Cambié la propiedad para usar el inicializador con cuerpo de expresión y el comando CanExecute dejó de funcionar.
Esto es lo que parecía y esto es lo que estaba sucediendo.
esto es a lo que lo cambié.
La diferencia aquí es que cuando uso
{ get; } =
creo y hago referencia al mismo comando en esa propiedad. Cuando uso=>
realmente creo un nuevo comando y lo devuelvo cada vez que se llama a la propiedad. Por lo tanto, nunca pude actualizar elCanExecute
comando porque siempre le decía que actualizara una nueva referencia de ese comando.Dicho todo esto, si solo está apuntando a un campo de respaldo, entonces funciona bien. Esto solo ocurre cuando el cuerpo automático o de expresión crea el valor de retorno.
fuente
Esta es una nueva característica de C # 6 llamada miembro con cuerpo de expresión que le permite definir una propiedad getter usando una función similar a lambda.
Si bien se considera azúcar sintáctico para lo siguiente, es posible que no produzcan IL idéntica:
Resulta que si compila ambas versiones de lo anterior y compara la IL generada para cada una, verá que son casi iguales.
Aquí está el IL para la versión clásica en esta respuesta cuando se define en una clase llamada
TestClass
:Y aquí está el IL para la versión del miembro con cuerpo de expresión cuando se define en una clase llamada
TestClass
:Consulte https://msdn.microsoft.com/en-us/magazine/dn802602.aspx para obtener más información sobre esta y otras características nuevas en C # 6.
Vea esta publicación Diferencia entre propiedad y campo en C # 3.0+ sobre la diferencia entre un campo y un captador de propiedad en C #.
Actualizar:
Tenga en cuenta que los miembros con cuerpo de expresión se expandieron para incluir propiedades, constructores, finalizadores e indexadores en C # 7.0.
fuente
Se llama Expression Bodied Member y se introdujo en C # 6. Es simplemente azúcar sintáctico sobre una
get
única propiedad.Es equivalente a:
Está disponible un equivalente de una declaración de método:
Principalmente permitiéndole acortar de repetitivo.
fuente
Otro punto importante si está usando C # 6:
'=>' se puede usar en lugar de 'get' y es solo para métodos 'get only' ; no se puede usar con un 'set'.
Para C # 7, vea el comentario de @avenmore a continuación: ahora se puede usar en más lugares. Aquí hay una buena referencia: https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
fuente
Para la siguiente declaración compartida por Alex Booker en su respuesta
Consulte la siguiente captura de pantalla , muestra cómo funciona esta declaración (usando el enlace SharpLab )
se convierte a
Captura de pantalla:
fuente