I came across some code that said
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
Now I am somewhat familiar with Lambda expressions. I just have not seen it used it this way.
What would be the difference between the above statement and
public int MaxHealth = x ? y:z;
What you're looking at is an expression-bodied member not a lambda expression.
When the compiler encounters an expression-bodied property member, it essentially converts it to a getter like this:
(You can verify this for yourself by pumping the code into a tool called TryRoslyn.)
Expression-bodied members - like most C# 6 features - are just syntactic sugar. This means that they don’t provide functionality that couldn't otherwise be achieved through existing features. Instead, these new features allow a more expressive and succinct syntax to be used
As you can see, expression-bodied members have a handful of shortcuts that make property members more compact:
return
statement because the compiler can infer that you want to return the result of the expressionget
keyword because it is implied by the use of the expression-bodied member syntax.I have made the final point bold because it is relevant to your actual question, which I will answer now.
The difference between...
And...
Is the same as the difference between...
And...
Which - if you understand properties - should be obvious.
Just to be clear, though: the first listing is a property with a getter under the hood that will be called each time you access it. The second listing is is a field with a field initializer, whose expression is only evaluated once, when the type is instantiated.
This difference in syntax is actually quite subtle and can lead to a "gotcha" which is described by Bill Wagner in a post entitled "A C# 6 gotcha: Initialization vs. Expression Bodied Members".
While expression-bodied members are lambda expression-like, they are not lambda expressions. The fundamental difference is that a lambda expression results in either a delegate instance or an expression tree. Expression-bodied members are just a directive to the compiler to generate a property behind the scenes. The similarity (more or less) starts and end with the arrow (
=>
).I'll also add that expression-bodied members are not limited to property members. They work on all these members:
However, they do not work on these members:
This is a new feature of C# 6 called an expression bodied member that allows you to define a getter only property using a lambda like function.
While it is considered syntactic sugar for the following, they may not produce identical IL:
It turns out that if you compile both versions of the above and compare the IL generated for each you'll see that they are NEARLY the same.
Here is the IL for the classic version in this answer when defined in a class named
TestClass
:And here is the IL for the expression bodied member version when defined in a class named
TestClass
:See https://msdn.microsoft.com/en-us/magazine/dn802602.aspx for more information on this and other new features in C# 6.
See this post Difference between Property and Field in C# 3.0+ on the difference between a field and a property getter in C#.
It is called Expression Bodied Member and it was introduced in C# 6. It is merely syntactic sugar over a
get
only property.It is equivalent to:
An equivalent of a method declaration is avaliable:
Mainly allowing you shortening of boilerplate.
One other significant point is that '=>' can be used instead of 'get' and is only for 'get only' methods - it can't be used with a 'set' .
Ok... I made a comment that they were different but couldn't explain exactly how but now I know.
is not the same as
Here's the difference...
When you use the auto initializer the property creates the instance of value and uses that value persistently. In the above post there is a broken link to Bill Wagner, that explains this well, and I searched the correct link to understand it myself.
In my situation I had my property auto initialize a command in a ViewModel for a View. I changed the property to use expression bodied initializer and the command CanExecute stopped working.
Here's what it looked like and here's what was happening.
here's what I changed it to.
The difference here is when I use
{ get; } =
I create and reference the SAME command in that property. When I use=>
I actually create a new command and return it every time the property is called. Therefore, I could never update theCanExecute
on my command because I was always telling it to update a new reference of that command.All that said, if you are just pointing to a backing field then it works fine. This only happens when the auto or expression body creates the return value.