我看到一些代码说
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
现在我对Lambda表达式有点熟悉了。我只是没见过它这样使用。
上述陈述和两者之间的区别是什么
public int MaxHealth = x ? y:z;
我看到一些代码说
public int MaxHealth =>
Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) :
0;
现在我对Lambda表达式有点熟悉了。我只是没见过它这样使用。
上述陈述和两者之间的区别是什么
public int MaxHealth = x ? y:z;
当前回答
以下是亚历克斯·布克在他们的回答中分享的声明
当编译器遇到表达式体的属性成员时,它本质上是将其转换为这样的getter:
请看下面的截图,它展示了这个语句(使用SharpLab链接)
public string APIBasePath => Configuration.ToolsAPIBasePath;
皈依
public string APIBasePath
{
get
{
return Configuration.ToolsAPIBasePath;
}
}
截图:
其他回答
它被称为表达式体成员,是在c# 6中引入的。它只是get only属性上的语法修饰。
它相当于:
public int MaxHealth { get { return Memory[Address].IsValid ?
Memory[Address].Read<int>(Offs.Life.MaxHp) : 0; }
一个等效的方法声明是可用的:
public string HelloWorld() => "Hello World";
主要是让你缩短样板。
如果你使用的是c# 6,还有一点很重要:
'=>'可以用来代替'get',并且只用于'get only'方法-它不能与'set'一起使用。
对于c# 7,请看下面来自@avenmore的评论——它现在可以在更多的地方使用。这里有一个很好的参考- https://csharp.christiannagel.com/2017/01/25/expressionbodiedmembers/
这是c# 6的一个新特性,称为表达式体成员,它允许您使用类lambda函数定义仅为getter的属性。
虽然它被认为是以下语法糖,但它们可能不会产生相同的IL:
public int MaxHealth
{
get
{
return Memory[Address].IsValid
? Memory[Address].Read<int>(Offs.Life.MaxHp)
: 0;
}
}
事实证明,如果您编译上述两个版本并比较为每个版本生成的IL,您将看到它们几乎相同。
下面是在一个名为TestClass的类中定义的经典版本的IL:
.property instance int32 MaxHealth()
{
.get instance int32 TestClass::get_MaxHealth()
}
.method public hidebysig specialname
instance int32 get_MaxHealth () cil managed
{
// Method begins at RVA 0x2458
// Code size 71 (0x47)
.maxstack 2
.locals init (
[0] int32
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
IL_0007: ldarg.0
IL_0008: ldfld int64 TestClass::Address
IL_000d: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
IL_0012: ldfld bool MemoryAddress::IsValid
IL_0017: brtrue.s IL_001c
IL_0019: ldc.i4.0
IL_001a: br.s IL_0042
IL_001c: ldarg.0
IL_001d: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
IL_0022: ldarg.0
IL_0023: ldfld int64 TestClass::Address
IL_0028: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
IL_002d: ldarg.0
IL_002e: ldfld class Offs TestClass::Offs
IL_0033: ldfld class Life Offs::Life
IL_0038: ldfld int64 Life::MaxHp
IL_003d: callvirt instance !!0 MemoryAddress::Read<int32>(int64)
IL_0042: stloc.0
IL_0043: br.s IL_0045
IL_0045: ldloc.0
IL_0046: ret
} // end of method TestClass::get_MaxHealth
下面是在一个名为TestClass的类中定义的表达式体成员版本的IL:
.property instance int32 MaxHealth()
{
.get instance int32 TestClass::get_MaxHealth()
}
.method public hidebysig specialname
instance int32 get_MaxHealth () cil managed
{
// Method begins at RVA 0x2458
// Code size 66 (0x42)
.maxstack 2
IL_0000: ldarg.0
IL_0001: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
IL_0006: ldarg.0
IL_0007: ldfld int64 TestClass::Address
IL_000c: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
IL_0011: ldfld bool MemoryAddress::IsValid
IL_0016: brtrue.s IL_001b
IL_0018: ldc.i4.0
IL_0019: br.s IL_0041
IL_001b: ldarg.0
IL_001c: ldfld class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress> TestClass::Memory
IL_0021: ldarg.0
IL_0022: ldfld int64 TestClass::Address
IL_0027: callvirt instance !1 class [mscorlib]System.Collections.Generic.Dictionary`2<int64, class MemoryAddress>::get_Item(!0)
IL_002c: ldarg.0
IL_002d: ldfld class Offs TestClass::Offs
IL_0032: ldfld class Life Offs::Life
IL_0037: ldfld int64 Life::MaxHp
IL_003c: callvirt instance !!0 MemoryAddress::Read<int32>(int64)
IL_0041: ret
} // end of method TestClass::get_MaxHealth
有关c# 6中的这个特性和其他新特性的更多信息,请参阅https://msdn.microsoft.com/en-us/magazine/dn802602.aspx。
请参阅c# 3.0+中属性和字段的区别这篇关于c#中字段和属性getter之间区别的文章。
更新:
注意,在c# 7.0中,表达式体成员被扩展到包括属性、构造函数、终结器和索引器。
以下是亚历克斯·布克在他们的回答中分享的声明
当编译器遇到表达式体的属性成员时,它本质上是将其转换为这样的getter:
请看下面的截图,它展示了这个语句(使用SharpLab链接)
public string APIBasePath => Configuration.ToolsAPIBasePath;
皈依
public string APIBasePath
{
get
{
return Configuration.ToolsAPIBasePath;
}
}
截图:
你也可以使用箭头作为get访问器:
private string foo = "foo";
private string bar
{
get => $"{foo}bar";
set
{
foo = value;
}
}