不同的吸气剂样式之间的C#差异


154

我有时确实会看到getter属性的缩写。例如,这两种类型:

public int Number { get; } = 0

public int Number => 0;

有人可以告诉我两者之间是否有任何区别。他们的行为如何?它们都是只读的吗?

Answers:


266

是的,它们都是只读的,但是有所不同。在第一个中,有一个支持字段,该字段在构造函数执行之前被初始化为0。您只能在构造函数中更改值,就像常规的只读字段一样。getter本身仅返回该字段的值。

在第二个中,getter每次都返回0,并且不涉及任何字段。

因此,为了避免使用任何自动实现的属性或表达式主体成员,我们具有:

第一版

private readonly int _number = 0;
public int Number { get { return _number; } }

第二版

public int Number { get { return 0; } }

可以看到一个更清晰的差异示例:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

如果创建单个对象,则其CreationTime属性将始终给出相同的结果-因为它存储在只读字段中,并在对象构造时初始化。但是,每次访问该CurrentTime属性时,都会导致DateTime.UtcNow对其进行评估,因此您可能会得到不同的结果。


23
请注意,第二个版本并不总是返回相同的值。一个很好的例子就是你是否返回random.NextInt()。第一个版本将对其进行一次评估,并且始终具有相同的值。秒将每次返回一个新值。

248

一种区别是何时0评估:在对象创建时或在使用属性时。

使用DateTime属性可以更好地看到这一点:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

Start属性将继续返回相同的时间(创建实例的时间),同时会Now更改以反映当前时间。

说明

第一个版本(“开始”)提供了一个初始值,该初始值甚至可能被构造方法覆盖。因此,仅对它进行一次评估。
第二个版本(“ Now”)提供将成为此属性的“ getter”的表达式。因此,每次读取属性时都会对其进行评估。构造器甚至没有覆盖字段可以覆盖。


26
这是我认为最重要的区别。
马修(Matt)

14
可接受的答案最精确地定义了示例代码中的差异,但这解释了两种结构中更有用的差异。
卡米尔·德拉卡里

3
哇,您比著名的乔恩·斯凯特(Jon Skeet)本人更有投票权。
machine_1

21

这些是C#6语言功能。

第一个例子

public int Number { get; } = 0

第一个示例是仅吸气剂的auto属性。仅吸气剂自动属性的支持字段隐式声明为只读。

第二个例子

public int Number => 0;

第二个示例是类似属性的函数成员上的表达式主体。请注意,没有任何get关键字:使用表达式主体语法即可隐含该关键字。

两者都是只读的。


5
...但是正如Jon Skeet解释的那样,您可以更改第一个返回的值。
马丁·邦纳

2
@MartinBonner ...但仅在构造函数中。
丹尼斯·库珀斯

5
还是一如既往地通过反射(轻微的挑剔)
Marco Mp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.