2017-09-05 47 views
151

我有时会在getter的属性中看到缩写。例如。这两种类型:不同的getter样式之间的C#差异

public int Number { get; } = 0 

public int Number => 0; 

有人可以告诉我,如果这两者之间有任何区别。他们如何表现?他们都是只读吗?

回答

262

是的,它们都是只读的,但是有区别。在第一个中,有一个支持字段在构造函数执行之前被初始化为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进行评估,因此您将得到可能不同的结果。

+22

请注意,第二个版本并不总是返回相同的值。一个很好的例子是如果你返回'random.NextInt()'。第一个版本将评估一次,并始终具有相同的价值。第二个将每次返回一个新值。 – Hosch250

20

这些是C#6语言功能。

第一示例

public int Number { get; } = 0 

第一个例子是一个getter-only auto property。只有getter的auto属性的后台字段被隐式声明为只读。

第二示例

public int Number => 0; 

而第二个例子是expression bodies on property-like function members。请注意,没有任何get关键字:它通过使用表达式主体语法来暗示。

两者都是只读的。

+4

...但正如Jon Skeet解释的那样,您可以更改第一个返回的值。 –

+1

@MartinBonner ...但只在构造函数中。 –

+4

或一如既往地通过反思(小挑逗) –

246

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

你可以看到这个更好的DateTime属性:

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

    public DateTime Now => DateTime.Now; 
} 

Start财产不断返回相同的时间(创建实例时),而Now变化,以反映当前时间。

说明

第一个版本(“开始”)提供,其可以甚至由构造被覆盖的初始值。所以这只被评估一次。
第二个版本(“现在”)提供了将成为该属性的“getter”的表达式。所以每次读取属性时都会对其进行评估。甚至没有构造函数可以覆盖的支持字段。

+24

这是我认为的最重要的区别。 – Matthew

+13

接受的答案最准确地定义了示例代码中的差异,但这解释了两个结构中更有用的差异。 –

+2

哇,你比起着名的Jon Skeet本人得到了更多的选票。 –