仅 getter 自动属性和表达式正文属性有什么区别

本文关键字:属性 正文 什么 区别 表达式 getter | 更新日期: 2023-09-27 18:37:19

在 C# 6 中,可以使用仅 getter 自动属性来简化属性的实现。例如,如果我正在实现抽象Stream类:

public override bool CanRead { get; } = true;

但是,我也可以使用表达式主体编写它,这也是 C# 6 中的新功能:

public override bool CanRead => true;

两者之间有什么区别,我什么时候应该使用其中一个?

仅 getter 自动属性和表达式正文属性有什么区别

它们是两种不同事物的句法糖。前者初始化支持字段,并在字段初始化期间将其设置为赋值右侧的表达式。后者创建一个get,该完全执行表达式中的内容。

public override bool CanRead { get; } = true;

相当于

private readonly bool __backingFieldCanRead = true;
public override bool CanRead
{
    get
    {
        return __backingFieldCanRead;
    }
}

public override bool CanRead => true;

相当于

public override bool CanRead
{
    get
    {
        return true;
    }
}

它们的行为不同。第一种情况在创建对象和初始化字段时设置属性的值,另一种情况在每次调用属性的 getter 时计算表达式。在布尔值的简单情况下,行为是相同的。但是,如果表达式引起副作用,情况就不同了。请考虑以下示例:

class Program
{
    static void Main(string[] args)
    {
        var fooBar1 = new FooBar();
        Console.WriteLine(fooBar1.Baz);
        Console.WriteLine(fooBar1.Baz);
        var fooBar2 = new FooBar();
        Console.WriteLine(fooBar2.Baz);
        Console.WriteLine(fooBar2.Baz);
    }
}
public class FooBar
{
    private static int counter;
    public int Baz => counter++;
}

这里打印了"0、1、2、3"。每次调用属性的 getter 时,静态counter字段都会递增。但是,使用属性初始值设定项:

public int Baz { get; } = counter++;

然后打印"0, 0, 1, 1",因为表达式是在对象的构造函数中计算的。

在你在我们的例子中描述的情况下,我曾经更喜欢:

public override bool CanRead { get; } = true;

但是今天我通知说,此实现会导致支持字段的内存分配。因此,这个实现:bool CanRead => true;可以节省 4 个字节。