简单类型的只读自动属性:初始化程序VS表达式主体获取器

时间:2016-05-02 20:36:36

标签: c# c#-6.0 automatic-properties

在C#6.0中,新语法允许我们使用初始化程序编写只读自动属性:

M

同样,我们可以使用表达式body getter来编写它:

public bool AllowsDuplicates { get; } = true;

对于简单类型,这两个应该具有相同的效果:一个返回true的只读自动属性。

但他们中的一个比另一个更受欢迎吗?我怀疑前者使用了支持字段:

public bool AllowsDuplicates => true;

而后者变成了类似的东西:

private readonly bool _backingField = true;
public bool AllowsDuplicates {
    get {
        return _backingField;
    }
}

这是正确的,还是编译器比这更聪明?

2 个答案:

答案 0 :(得分:8)

  

我怀疑前者使用了支持字段

auto-property初始化程序确实创建了一个支持字段!你可以把它扔进ILSpy并在输出中看到它:

public class One
{
    public bool AllowsDuplicates
    {
        [CompilerGenerated]
        get
        {
            return this.<AllowsDuplicates>k__BackingField;
        }
    }

    public One()
    {
        this.<AllowsDuplicates>k__BackingField = true;
        base..ctor();
    }
}

public class Two
{
    public bool AllowsDuplicates
    {
        get
        {
            return true;
        }
    }
}
  

但他们中的一个比另一个更受欢迎吗?

对于问题中的特定示例,auto-property将允许构造函数请求bool并分配它。第二种风格不会。如果意图将其用作&#34;默认值&#34;在施工期间可以修改一次,然后自动财产是正确的选择。

class Test
{
    // Could assign this in the second constructor
    public bool AllowsDuplicates { get; } = true;

    // Cannot assign this in the second constructor
    public bool AllowsDuplicates => true;

    public Test()
    {
        // Default value used
    }

    public Test(bool value)
    {
        AllowsDuplicates = value;
    }
}

我已经看到表达身体语法胜出最多,因为它是一个用作属性的小功能的掩护。 Eric Lippert's dedoublifier中的结构有一个很好的例子:

public DoubleHelper(double d)
{
    this.RawBits = (ulong)BitConverter.DoubleToInt64Bits(d);
}

public ulong RawBits { get; }
// RawSign is 1 if zero or negative, 0 if zero or positive
public int RawSign => (int)(RawBits >> 63);
public int RawExponent => (int)(RawBits >> 52) & 0x7FF;
public long RawMantissa => (long)(RawBits & 0x000FFFFFFFFFFFFF);
public bool IsNaN => RawExponent == 0x7ff && RawMantissa != 0;
public bool IsInfinity => RawExponent == 0x7ff && RawMantissa == 0;
public bool IsZero => RawExponent == 0 && RawMantissa == 0;
public bool IsDenormal => RawExponent == 0 && RawMantissa != 0;

在构造函数中分配了一个值,其余的是基于它计算的属性值。

答案 1 :(得分:1)

  

我怀疑前者使用支持字段,而后者是   变成了类似的东西,是吗?

是的,就像你说的那样, Auto-property Initializer 设置声明时支持字段的值。

Expression-bodied get正文的语法简化。

  

但他们中的一个比另一个更受欢迎吗?

取决于,如果您的属性更复杂,只返回相同的值,例如ElapsedCurrent属性,或任何需要计算 Expression-bodied的内容更合适 在 Expression-bodied 中,定义每次访问属性时要执行的代码。

如果您的属性应该是不可变的,只需一个初始常量值,那么 Auto-property Initializer 将是首选。