What is the => assignment in C# in a property signature

前端 未结 7 1108
执念已碎
执念已碎 2020-11-22 00:29

I came across some code that said

public int MaxHealth => 
         Memory[Address].IsValid ? 
         Memory[Address].Read(Offs.Life.MaxHp)          


        
7条回答
  •  孤街浪徒
    2020-11-22 01:32

    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:

    public int MaxHealth
    {
        get
        {
            return Memory[Address].IsValid ? Memory[Address].Read(Offs.Life.MaxHp) : 0;
        }
    }
    

    (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:

    • There is no need to use a return statement because the compiler can infer that you want to return the result of the expression
    • There is no need to create a statement block because the body is only one expression
    • There is no need to use the get 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...

    // expression-bodied member property
    public int MaxHealth => x ? y:z;
    

    And...

    // field with field initializer
    public int MaxHealth = x ? y:z;
    

    Is the same as the difference between...

    public int MaxHealth
    {
        get
        {
            return x ? y:z;
        }
    }
    

    And...

    public int MaxHealth = x ? y:z;
    

    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:

    • Properties
    • Indexers
    • Methods
    • Operators

    Added in C# 7.0

    • Constructors
    • Finalizers

    However, they do not work on these members:

    • Nested Types
    • Events
    • Fields

提交回复
热议问题