不同getter风格之间C#的差异

WoI*_*IIe 153 c# getter coding-style shorthand

我有时会在getter的属性中看到缩写.例如这两种类型:

public int Number { get; } = 0

public int Number => 0;
Run Code Online (Sandbox Code Playgroud)

如果这两者之间有任何差异,有人可以告诉我.他们的表现如何?它们都是只读的吗?

Jon*_*eet 265

是的,它们都是只读的,但是有区别.在第一个中,有一个支持字段,在执行构造函数之前将其初始化为0.您只能在构造函数中更改值,就像常规的只读字段一样.getter本身只返回字段的值.

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

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

第一版

private readonly int _number = 0;
public int Number { get { return _number; } }
Run Code Online (Sandbox Code Playgroud)

第二版

public int Number { get { return 0; } }
Run Code Online (Sandbox Code Playgroud)

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

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;
Run Code Online (Sandbox Code Playgroud)

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

  • 请注意,第二个版本并不总是返回相同的值.一个很好的例子是你返回`random.NextInt()`.第一个版本将评估一次并始终具有相同的值.第二个将每次返回一个新值. (22认同)

Han*_*ing 248

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

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

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

    public DateTime Now => DateTime.Now;
}
Run Code Online (Sandbox Code Playgroud)

Start属性保持同时(在创建实例时)返回,而Now更改则反映当前时间.

说明:

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

  • 这是我认为最重要的区别. (24认同)
  • 接受的答案最精确地定义了示例代码中的差异,但这解释了两种结构中更有用的差异. (13认同)
  • 哇,你比着名的Jon Skeet本人有更多的选票. (2认同)

Jeh*_*hof 20

这些是C#6语言功能.

第一个例子

public int Number { get; } = 0
Run Code Online (Sandbox Code Playgroud)

第一个示例是仅限getter的自动属性.仅具有getter的auto属性的支持字段被隐式声明为readonly.

第二个例子

public int Number => 0;
Run Code Online (Sandbox Code Playgroud)

第二个例子是类似属性的函数成员的表达式主体.请注意,没有任何get关键字:使用表达式body语法暗示了这一点.

两者都是只读的.

  • ......但正如Jon Skeet所解释的那样,你可以改变第一个返回的值. (4认同)
  • 或者,一如既往地通过反思(轻微的挑剔) (4认同)
  • @MartinBonner ...但仅在构造函数中。 (2认同)