小编典典

=> 运算符在属性中的含义是什么?

all

我遇到了一些代码说

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

现在我对 Lambda 表达式有点熟悉了。我只是没有看到它以这种方式使用它。

上面的陈述和有什么区别

public int MaxHealth  = x ? y:z;

阅读 72

收藏
2022-04-26

共1个答案

小编典典

您正在查看的是表达式主体成员 而不是 lambda 表达式。

当编译器遇到表达式体 属性 成员时,它本质上将其转换为如下所示的 getter:

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

(您可以通过将代码注入一个名为TryRoslyn的工具来自己验证这一点。)

与大多数 C# 6 功能一样,表达式主体成员 只是
语法糖。这意味着它们不提供通过现有功能无法实现的功能。相反,这些新功能允许使用更具表现力和简洁的语法

如您所见,表达式体成员有一些快捷方式可以使属性成员更紧凑:

  • 不需要使用return语句,因为编译器可以推断出您想要返回表达式的结果
  • 无需创建语句块,因为主体只是一个表达式
  • 没有必要使用get关键字,因为它是通过使用表达式体成员语法来暗示的。

我将最后一点加粗,因为它与您的实际问题有关,我现在将回答。

和…之间的不同…

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

和…

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

是不是一样的区别…

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

和…

public int MaxHealth = x ? y:z;

其中 - 如果您了解属性 - 应该是显而易见的。

不过要明确一点:第一个清单是一个在引擎盖下有一个 getter
的属性,每次访问它时都会调用它。第二个清单是一个带有字段初始值设定项的字段,当类型被实例化时,它的表达式只计算一次。

这种语法上的差异实际上非常微妙,并且可能导致 Bill Wagner 在题为 “AC# 6 gotcha: Initialization vs.
Expression Bodied
Members”的帖子中描述的“陷阱”

虽然表达式体成员 类似于 lambda 表达式,但它们 不是 lambda 表达式。根本区别在于 lambda
表达式生成委托实例或表达式树。表达式体成员只是编译器在幕后生成属性的指令。相似性(或多或少)以箭头 ( =>) 开始和结束。

我还要补充一点,表达式体成员不仅限于属性成员。他们对所有这些成员起作用:

  • Properties
  • Indexers
  • Methods
  • Operators

Added in C# 7.0

However, they do not work on these members:

  • Nested Types
  • Events
  • Fields
2022-04-26