问题描述
我遇到了一些代码
public int MaxHealth =>内存[地址].IsValid ?内存[地址].Read(Offs.Life.MaxHp):0;
现在我对 Lambda 表达式有些熟悉了.我只是没有看到它这样使用它.
上面的语句和
有什么区别public int MaxHealth = x ?y:z;
你看到的是一个expression-bodied 成员 不是 lambda 表达式.
当编译器遇到表达式主体的 property 成员时,它实质上会将其转换为如下所示的 getter:
public int MaxHealth{得到{返回内存[地址].IsValid ?内存[地址].Read(Offs.Life.MaxHp) : 0;}}
(您可以通过将代码注入一个名为 TryRoslyn>a 的工具来验证这一点./p>
表达式主体成员 - 就像大多数 C# 6 功能一样 - 只是 语法糖.这意味着它们不提供通过现有功能无法实现的功能.相反,这些新功能允许使用更具表现力和简洁的语法
如您所见,表达式体成员有一些使属性成员更紧凑的快捷方式:
- 不需要使用
return
语句,因为编译器可以推断出你想要返回表达式的结果 - 不需要创建语句块,因为主体只是一个表达式
- 没有必要使用
get
关键字,因为它是通过使用表达式体成员语法来暗示的.
我将最后一点加粗,因为它与您的实际问题相关,我现在将回答.
...的区别
//表达式体成员属性公共 int MaxHealth =>X ?y:z;
还有……
//带有字段初始化器的字段公共 int MaxHealth = x ?y:z;
和...的区别是一样的
public int MaxHealth{得到{返回 x ?y:z;}}
还有……
public int MaxHealth = x ?y:z;
如果您了解属性,这应该是显而易见的.
但要明确一点:第一个清单是一个在引擎盖下有一个 getter 的属性,每次访问它时都会调用它.第二个清单是一个带有字段初始值设定项的字段,当类型被实例化时,它的表达式只计算一次.
语法上的这种差异实际上非常微妙,可能会导致 Bill Wagner 在题为 "AC# 6 gotcha:初始化与表达式主体成员".
虽然表达式体成员是 lambda 表达式-类似,但它们不是 lambda 表达式.根本区别在于 lambda 表达式生成委托实例或表达式树.表达式体成员只是编译器在幕后生成属性的指令.相似度(或多或少)以箭头 (=>
) 开始和结束.
我还要补充一点,表达式体成员不限于属性成员.他们对所有这些成员都起作用:
- 属性
- 索引器
- 方法
- 运营商
添加在 C# 7.0
- 构造函数
- 终结者
但是,它们不适用于这些成员:
- 嵌套类型
- 活动
- 字段
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:
public int MaxHealth
{
get
{
return Memory[Address].IsValid ? Memory[Address].Read<int>(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
这篇关于=> 是什么?属性签名中的 C# 赋值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!