是否可以强制自动属性使用只读后备字段?

我的项目包含大量具有属性的类,其后备字段标记为只读,因为它们仅在构造时设置。 作为一种风格问题,我喜欢使用自动属性,因为它消除了大量的样板代码,并鼓励使用属性成员而不是支持字段。 但是,当使用自动属性时,我失去了我的支持字段的“readonly-ness”。 我理解编译器/运行时能够在以这种方式标记字段时利用一些性能增强,所以我希望能够将我的auto-property标记为readonly,如下所示:

[ReadOnly] public string LastName { get; } 

而不是

 private readonly string _LastName; public string LastName { get { return _LastName; } } 

有没有一些机制可以做到这一点? 如果没有,自定义支持字段的性能增益是否真的值得?

我认为,将该字段公开为公共是另一种选择,以这种方式公开字段似乎是错误的。 即

 public readonly string LastName; 

我不敢,但你可以这样做:

 public string LastName { get; private set; } 

不像readonly那么好,但也不是太糟糕。

不,不幸的是没有办法做到这一点。 就个人而言,我认为C#中自动实现的属性缺少两件事 – 一个默认值(我相信将在VB10中)和只能在构造函数中设置的只读属性。 换句话说,我希望能够做到:

 public class Foo { public string Tag { get; internal set; } = "Default value"; // The "readonly" would imply "private" as it could only // be set from a constructor in the same class public int Value { get; readonly set; } public Foo() { // Valid to set property here, but nowhere else Value = 20; } } 

正如Jared所提到的,这意味着将对属性设置器的编译器调用更改为简单的字段分配,并确保它们仅在构造函数中发生。

这将使编写不可变类型更简单。 不幸的是,C#4的情况不会有所改善。我们希望我们能为C#5获得类似的东西……

不,它不是,如果没有重大调整,这个function将毫无用处。

只能从构造函数中validationreadonly字段。 只能从生成的setter中设置自动实现的属性。 这些是不兼容的要求,将产生无法validation的代码。

是的,您可能会使编译器足够智能以忽略setter并直接进入构造函数中的支持字段。 但在制定者本身仍然是无法核实的。 编译器需要从生成的代码中省略它,因为它将生成一个真正的只读属性。 这会产生另一个矛盾,因为您仍然需要对该属性执行赋值语句。

 Foo() { SomeProperty = "somevalue"; } 

在这种情况下,代码看起来像是在属性上调用setter。 但实际上没有要调用的setter,因为它必须从最终代码中省略。

编辑

这并不是说它无法完成。 它可以但需要C#的一些工作。

特别是,他们必须提供一种方法来设置不具有设定器的属性的支持字段。 有几种方法可以做到这一点。

  • 允许用户访问自动实现的属性的支持字段
  • 即使没有setter,也允许setter样式语法,让编译器将其转换为引擎下的字段访问
  • 发明一些新的语法

我不是说这些都是好的选择,只是使这种类型的function工作的可能性。

从C#6.0开始,答案是肯定的。 您的示例可以编写如下,编译器会自动生成属性后面的只读字段。 这称为仅限getter的自动属性。

 public string LastName { get; } 

来自https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

结构和类声明中只提供仅限getter的自动属性,但它们对结构特别重要,因为结构是不可变的最佳实践指南。 而不是声明一个只读属性并在C#6.0之前初始化它所需的六行左右,现在只需要单行声明和构造函数中的赋值。 因此,不可变结构的声明现在不仅是结构的正确编程模式,而且是更简单的模式 – 从先前语法的一个非常理解的变化,其中编码正确地需要更多的努力。

我更喜欢真正的readonly后备字段,因为这可以保证我在构建后不会更改该后备字段。

不,不。 没有办法做到这一点,只读备份字段没有性能提升。