Je suis tombé sur un code qui disait
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Maintenant, je connais un peu les expressions Lambda. Je ne l'ai tout simplement pas vu utilisé de cette façon.
Quelle serait la différence entre la déclaration ci-dessus et
public int MaxHealth = x ? y:z;
Réponses:
Ce que vous regardez est un membre d'expression corporelle et non une expression lambda.
Lorsque le compilateur rencontre un membre de propriété doté d'un corps d'expression , il le convertit essentiellement en un getter comme celui-ci:
(Vous pouvez le vérifier par vous-même en injectant le code dans un outil appelé TryRoslyn .)
Les membres dotés d'une expression - comme la plupart des fonctionnalités C # 6 - ne sont que du sucre syntaxique . Cela signifie qu'ils ne fournissent pas de fonctionnalités qui n'auraient pas pu être obtenues autrement grâce aux fonctionnalités existantes. Au lieu de cela, ces nouvelles fonctionnalités permettent d'utiliser une syntaxe plus expressive et succincte
Comme vous pouvez le voir, les membres dotés d'une expression ont une poignée de raccourcis qui rendent les membres de propriété plus compacts:
return
instruction car le compilateur peut déduire que vous souhaitez renvoyer le résultat de l'expressionget
mot - clé car il est impliqué par l'utilisation de la syntaxe des membres avec corps d'expression.J'ai mis le dernier point en gras, car il est pertinent pour votre question actuelle, à laquelle je vais répondre maintenant.
La différence entre...
Et...
Est la même que la différence entre ...
Et...
Ce qui - si vous comprenez les propriétés - devrait être évident.
Pour être clair, cependant: la première annonce est une propriété avec un getter sous le capot qui sera appelée chaque fois que vous y accéderez. La deuxième liste est un champ avec un initialiseur de champ, dont l'expression n'est évaluée qu'une seule fois, lorsque le type est instancié.
Cette différence de syntaxe est en fait assez subtile et peut conduire à un "gotcha" qui est décrit par Bill Wagner dans un article intitulé "AC # 6 gotcha: Initialization vs. Expression Bodied Members" .
Bien que les membres dotés d'une expression ressemblent à une expression lambda , ils ne sont pas des expressions lambda. La différence fondamentale est qu'une expression lambda aboutit à une instance déléguée ou à un arbre d'expression. Les membres dotés d'expressions ne sont qu'une directive adressée au compilateur pour générer une propriété en arrière-plan. La similitude (plus ou moins) commence et se termine par la flèche (
=>
).J'ajouterai également que les membres d'expression ne sont pas limités aux membres de propriété. Ils travaillent sur tous ces membres:
Ajouté dans C # 7.0
Cependant, ils ne fonctionnent pas sur ces membres:
la source
Ok ... J'ai fait un commentaire qu'ils étaient différents mais ne pouvaient pas expliquer exactement comment mais maintenant je sais.
n'est pas la même chose que
Voici la différence ...
Lorsque vous utilisez l'initialiseur automatique, la propriété crée l'instance de valeur et utilise cette valeur de manière persistante. Dans le post ci-dessus, il y a un lien brisé vers Bill Wagner, cela explique bien cela, et j'ai cherché le bon lien pour le comprendre moi-même.
Dans ma situation, j'avais ma propriété initialiser automatiquement une commande dans un ViewModel pour une vue. J'ai modifié la propriété pour utiliser l'initialiseur d'expression corporel et la commande CanExecute a cessé de fonctionner.
Voici à quoi cela ressemblait et voici ce qui se passait.
voici ce que je l'ai changé.
La différence ici est lorsque j'utilise,
{ get; } =
je crée et référence la même commande dans cette propriété. Lorsque j'utilise,=>
je crée en fait une nouvelle commande et la renvoie à chaque appel de la propriété. Par conséquent, je n'ai jamais pu mettre à jour leCanExecute
sur ma commande car je lui disais toujours de mettre à jour une nouvelle référence de cette commande.Cela dit, si vous pointez simplement vers un champ de support, cela fonctionne très bien. Cela se produit uniquement lorsque le corps auto ou expression crée la valeur de retour.
la source
Il s'agit d'une nouvelle fonctionnalité de C # 6 appelée membre bodied d'expression qui vous permet de définir une propriété getter uniquement à l'aide d'une fonction de type lambda.
Bien qu'il soit considéré comme du sucre syntaxique pour les éléments suivants, ils peuvent ne pas produire d'IL identique:
Il s'avère que si vous compilez les deux versions de ce qui précède et comparez l'IL généré pour chacune, vous verrez qu'elles sont presque les mêmes.
Voici l'IL de la version classique dans cette réponse lorsqu'elle est définie dans une classe nommée
TestClass
:Et voici l'IL de la version de membre de l'expression corporelle lorsqu'elle est définie dans une classe nommée
TestClass
:Voir https://msdn.microsoft.com/en-us/magazine/dn802602.aspx pour plus d'informations à ce sujet et d'autres nouvelles fonctionnalités de C # 6.
Voir cet article Différence entre propriété et champ en C # 3.0+ sur la différence entre un champ et un getter de propriété en C #.
Mettre à jour:
Notez que les membres dotés d'une expression ont été développés pour inclure des propriétés, des constructeurs, des finaliseurs et des indexeurs dans C # 7.0.
la source
Il s'appelle Expression Bodied Member et a été introduit en C # 6. Il s'agit simplement de sucre syntaxique sur une
get
seule propriété.Il équivaut à:
Un équivalent d'une déclaration de méthode est disponible:
Vous permettant principalement de raccourcir le passe-partout.
la source
Un autre point important si vous utilisez C # 6:
'=>' peut être utilisé au lieu de 'get' et est uniquement pour les méthodes 'get only' - il ne peut pas être utilisé avec un 'set'.
Pour C # 7, voir le commentaire de @avenmore ci-dessous - il peut maintenant être utilisé dans plus d'endroits. Voici une bonne référence - https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
la source
Pour la déclaration suivante partagée par Alex Booker dans leur réponse
Veuillez voir la capture d'écran suivante , elle montre comment cette déclaration (en utilisant le lien SharpLab )
convertit en
Capture d'écran:
la source