Me deparei com um código que dizia
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Agora estou familiarizado com as expressões Lambda. Eu simplesmente não o vi dessa maneira.
Qual seria a diferença entre a afirmação acima e
public int MaxHealth = x ? y:z;
Respostas:
O que você está vendo é um membro com expressão, não uma expressão lambda.
Quando o compilador encontra um membro da propriedade do corpo da expressão , ele basicamente o converte em um getter como este:
(Você pode verificar isso por si mesmo bombeando o código para uma ferramenta chamada TryRoslyn .)
Membros com corpo de expressão - como a maioria dos recursos do C # 6 - são apenas açúcar sintático . Isso significa que eles não fornecem funcionalidades que não poderiam ser alcançadas por meio de recursos existentes. Em vez disso, esses novos recursos permitem que uma sintaxe mais expressiva e sucinta seja usada
Como você pode ver, os membros com expressão têm vários atalhos que tornam os membros da propriedade mais compactos:
return
instrução porque o compilador pode inferir que você deseja retornar o resultado da expressãoget
palavra-chave, porque está implícita no uso da sintaxe do membro com corpo de expressão.Tornei o ponto final em negrito, porque é relevante para a sua pergunta real, que responderei agora.
A diferença entre...
E...
É o mesmo que a diferença entre ...
E...
O que - se você entende as propriedades - deve ser óbvio.
Apenas para ficar claro: a primeira listagem é uma propriedade com um getter sob o capô que será chamada sempre que você acessá-la. A segunda listagem é um campo com um inicializador de campos, cuja expressão é avaliada apenas uma vez, quando o tipo é instanciado.
Essa diferença de sintaxe é realmente bastante sutil e pode levar a uma "pegadinha", descrita por Bill Wagner em um post intitulado "Pegada da AC # 6: inicialização versus membros corporados de expressão" .
Enquanto membros com expressão corporal são semelhantes a expressões lambda , eles não são expressões lambda. A diferença fundamental é que uma expressão lambda resulta em uma instância delegada ou em uma árvore de expressão. Membros com corpo de expressão são apenas uma diretiva para o compilador para gerar uma propriedade nos bastidores. A semelhança (mais ou menos) começa e termina com a seta (
=>
).Também acrescentarei que membros com expressão corporal não se limitam a membros de propriedade. Eles trabalham em todos esses membros:
Adicionado no C # 7.0
No entanto, eles não funcionam com esses membros:
fonte
Ok ... Fiz um comentário de que eram diferentes, mas não conseguiam explicar exatamente como, mas agora eu sei.
não é o mesmo que
Aqui está a diferença ...
Quando você usa o inicializador automático, a propriedade cria a instância do valor e usa esse valor persistentemente. No post acima, há um link quebrado para Bill Wagner, que explica isso bem, e eu procurei no link correto para entender eu mesmo.
Na minha situação, minha propriedade inicializou automaticamente um comando em um ViewModel para um View. Alterei a propriedade para usar o inicializador corporativo de expressão e o comando CanExecute parou de funcionar.
Aqui está o que parecia e aqui está o que estava acontecendo.
aqui está o que eu mudei para.
A diferença aqui é que quando eu uso
{ get; } =
, crio e faço referência ao mesmo comando nessa propriedade. Quando uso=>
, na verdade, crio um novo comando e o retorno sempre que a propriedade é chamada. Portanto, nunca pude atualizar oCanExecute
comando, pois estava sempre dizendo para atualizar uma nova referência desse comando.Tudo isso dito, se você está apenas apontando para um campo de apoio, ele funciona bem. Isso só acontece quando o corpo automático ou de expressão cria o valor de retorno.
fonte
Esse é um novo recurso do C # 6 chamado membro incorporado da expressão que permite definir uma propriedade getter only usando uma função semelhante a lambda.
Embora seja considerado açúcar sintático para o seguinte, eles podem não produzir IL idêntica:
Acontece que, se você compilar as duas versões acima e comparar o IL gerado para cada uma delas, verá que elas são quase as mesmas.
Aqui está o IL da versão clássica nesta resposta quando definida em uma classe denominada
TestClass
:E aqui está o IL da versão do membro corporativo da expressão quando definido em uma classe denominada
TestClass
:Consulte https://msdn.microsoft.com/en-us/magazine/dn802602.aspx para obter mais informações sobre esse e outros novos recursos do C # 6.
Veja este post Diferença entre propriedade e campo em C # 3.0+ sobre a diferença entre um campo e um getter de propriedade em c #.
Atualizar:
Observe que os membros com expressão foram expandidos para incluir propriedades, construtores, finalizadores e indexadores no C # 7.0.
fonte
É chamado de Membro Corporado da Expressão e foi introduzido no C # 6. É apenas açúcar sintático sobre uma
get
única propriedade.É equivalente a:
Um equivalente de uma declaração de método está disponível:
Principalmente permitindo o encurtamento do clichê.
fonte
Outro ponto significativo se você estiver usando o C # 6:
'=>' pode ser usado em vez de 'get' e é apenas para os métodos 'get only' - não pode ser usado com um 'set'.
Para o C # 7, veja o comentário de @avenmore abaixo - agora ele pode ser usado em mais lugares. Aqui está uma boa referência - https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
fonte
Pela seguinte declaração compartilhada por Alex Booker em sua resposta
Por favor, veja a captura de tela a seguir , mostra como esta declaração (usando o link SharpLab )
converte para
Captura de tela:
fonte