我总能找到关于 C# 特性的合法讨论,而且几乎所有事情都有利弊,但在这种情况下,我真的找不到任何人建议不要使用自动实现的属性。
我在今天的代码审查中遇到了这个问题,当我询问我的同行时,我们也无法达成共识。我不喜欢模棱两可,我想知道至少一个能回答你问题的热门问题:
就像要知道要舔多少次才能到达 Tootsie Roll Tootsie Pop 的中心,我决定“让我们找出答案”。
让我们首先实际做一个苹果与苹果的比较。
假设我们有两个类:
public class C
{
private int z;
public int Z
{
get { return z;}
}
}
public class Q
{
public int Z { get; }
}
第一个类是手动后备存储,第二个是自动编译器生成的版本。
让我们看看为每个生成的 IL。
一、手动后备存储版本:
// Fields
.field private int32 z
// Methods
.method public hidebysig specialname
instance int32 get_Z () cil managed
{
// Method begins at RVA 0x2050
// Code size 12 (0xc)
.maxstack 1
.locals init (
[0] int32
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 C::z
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method C::get_Z
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2068
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method C::.ctor
// Properties
.property instance int32 Z()
{
.get instance int32 C::get_Z()
}
现在让我们看看第二类的 IL:
// Fields
.field private initonly int32 '<Z>k__BackingField'
.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [System.Private.CoreLib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
// Methods
.method public hidebysig specialname
instance int32 get_Z () cil managed
{
.custom instance void [System.Private.CoreLib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2071
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 Q::'<Z>k__BackingField'
IL_0006: ret
} // end of method Q::get_Z
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2068
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method Q::.ctor
// Properties
.property instance int32 Z()
{
.get instance int32 Q::get_Z()
}
忽略用于添加可调试属性的额外编译器生成代码,它不会添加明显的可执行代码,生成的代码似乎没有任何差异。
现在,您可能会争辩说您的问题没有得到解答,但请考虑...
如果您曾经编写过参与绑定的属性,例如:
private string name;
public string Name
{
get { return name; }
set { SetProperty (ref name, value);
}
那么后备存储就是要走的路。
另一方面,使用 Visual Studio 编辑器中的“prop” 快捷方式来生成自动属性非常方便,而且比 all快得多> 输入 ;)
所以到最后,对于锤子来说,一切看起来都像钉子。不要当锤子。