【问题标题】:What is the difference between getter-only auto properties and expression body properties?仅限 getter 的自动属性和表达式主体属性有什么区别?
【发布时间】:2015-03-10 18:00:31
【问题描述】:

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

public override bool CanRead { get; } = true;

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

public override bool CanRead => true;

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

【问题讨论】:

    标签: c# c#-6.0


    【解决方案1】:

    它们是两种不同事物的语法糖。前者初始化一个支持字段,并在字段初始化期间将其设置为赋值右侧的表达式。后者创建了一个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”,因为表达式是在对象的构造函数中计算的。

    【讨论】:

    • 从技术上讲,在第一种情况下,生成的支持字段是否也是 readonly?
    • 支持字段的分配就像在字段初始化程序中分配一样,而不是在构造函数的主体中。如果基类调用虚拟方法,您可以观察到这种差异,这发生在构造函数主体执行之前。诚然,这是一个微妙的区别:)
    • @JonSkeet 哦,你是对的,字段是initonly
    • @vcsjones:是的,尽管这并没有阻止它在构造函数主体中被分配(根据我的经验,这是更常见的用法)。只是时间不同而已。
    【解决方案2】:

    在您在我们的示例中描述的情况下,我以前更喜欢:

    public override bool CanRead { get; } = true;
    

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

    【讨论】:

      猜你喜欢
      • 2020-06-23
      • 1970-01-01
      • 2011-11-14
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 2016-04-29
      相关资源
      最近更新 更多