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

时间:2009-06-26 19:16:34

标签: c# .net

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

[ReadOnly]
public string LastName { get; }

而不是

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

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

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

public readonly string LastName;

6 个答案:

答案 0 :(得分:13)

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

public string LastName { get; private set; }

不如readonly好,但也不算太差。

答案 1 :(得分:8)

不,不幸的是没有办法做到这一点。就个人而言,我认为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所提到的,这意味着将对属性setter的编译器调用更改为简单的字段赋值,并确保它们仅在构造函数中发生。

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

答案 2 :(得分:4)

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

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

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

Foo() {
  SomeProperty = "somevalue";
}

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

修改

这并不是说不能做到。它可以但需要C#的一些工作。

特别是他们必须提供一种方法来设置不能有setter的属性的支持字段。有几种方法可以做到。

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

我并不是说这些都是不错的选择,只是使这种功能有效的可能性。

答案 3 :(得分:3)

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

public string LastName { get; }

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

  

在结构和类中都可以使用仅限Getter的自动属性   声明,但它们对结构特别重要,因为   结构不可变的最佳实践指南。而不是   需要六行左右来声明一个只读属性并进行初始化   它在C#6.0之前,现在是单行声明和赋值   从构造函数中完成所有需要。因此,申报   不可变结构现在不仅是正确的编程模式   结构,但也更简单的模式 - 一个非常赞赏的变化   从先前的语法中,编码正确地需要更多努力。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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