【问题标题】:Is there a way to make readonly (not just private) automatic properties?有没有办法使只读(不仅仅是私有)自动属性?
【发布时间】:2009-10-08 09:35:51
【问题描述】:

自动属性让我替换这段代码:

private MyType myProperty;
public MyType MyProperty
{
    get { return myPropertyField; }
}

使用此代码:

public MyType MyProperty { get; private set; }

在这里和那里进行了一些更改 - 但有没有办法替换此代码:

private readonly MyType myProperty;
public MyType MyProperty
{
    get { return myPropertyField; }
}

有类似的东西吗?

【问题讨论】:

标签: c# readonly automatic-properties


【解决方案1】:

确实,目前没有办法做到这一点。

我们意识到在 C# 3 中我们产生了一些哲学上的矛盾。 LINQ 的设计在很大程度上沉浸在传统的不可变函数式编程风格中——执行被延迟,查询由不可变的单子表示,表达式树是不可变的,等等。

同时,对象初始化器、集合初始化器和自动道具都鼓励传统的基于可变组件的编程风格。似乎我们正在向两个方向推进——这表明了 C# 的本质;它是一种实用的编程语言,支持多种不同的编程风格。

但是,由于我们都是不可变编程风格的忠实拥护者,而且我们相信这种风格将带来好处,从而在未来无处不在的多核架构中更容易确保大规模多线程应用程序的正确性,我们'我绝对有兴趣找出一些方法来驯服我们引入的可变性。 Readonly autoprops 是一种明显的方法。一小步,但很好。

话虽如此,我们甚至还没有发布 C# 4,也没有宣布之后会有任何新的语言特性。您应该将我对未发布产品的假设功能的所有想法视为“仅用于娱乐目的”的推测,而不是承诺或公告。

【讨论】:

  • 我希望看到的一个相关功能是字段初始值设定项可以使用构造函数参数的一种方式。据我了解,字段初始值设定项实际上只是在构造函数的第一条语句之前插入的代码,并且在该上下文中运行,因此如果语言提供了访问这些参数的方法,它们就可以访问这些参数。我建议的实现:一种类似字段的语法,用于指定给定类型的某个命名的共构造函数参数将可用于字段初始值设定项;该类型的所有构造函数都必须具有这样的参数...
  • ...或链接到一个这样做的。这将允许诸如表示构造函数指定(且不可更改)大小的集合的类之类的东西让数组的声明以适当的大小对其进行初始化。如果这是唯一一次编写引用,将其放入声明中似乎比在一个地方声明并在另一个地方初始化要好。
  • @supercat:有趣的想法。事实上,C# 设计团队正在考虑一种稍微不同的机制。他们正在考虑向构造函数添加语法糖,以便更容易表达“这个 ctor 形式参数初始化这个只读字段”的想法,从而更容易简洁地编写不可变类型。不过,我不希望该功能很快发布。
  • 很高兴你喜欢这个主意;我希望 C# 和 vb.net 团队都可以合并版本,其中传入的东西变成真实字段(具有可指定的可访问性)、自动属性(同样)或仅在初始化程序或构造函数中可用的变量。在 vb.net 中,如果感兴趣的参数值应该保存在字段中,并且如果添加了额外的继承层(如果基类构造函数将值存储在字段中,则派生类初始值设定项),则可以实现所需的语义可以使用它们)但它有点难看。我认为 C# 根本做不到。
【解决方案2】:

不,但这个想法是tracked on Connect

【讨论】:

    【解决方案3】:

    不,很遗憾没有。我非常喜欢这个功能,它可能看起来像这样:

    public readonly string Name { get; }
    

    或者(有点奇怪)

    public readonly string Name { get; readonly set; }
    

    这将被转换成类似的东西:

    private readonly string <>_Name;
    
    public string Name { get { return <>_Name; } }
    

    不同的是,setter 调用将被允许 - 但仅限于构造函数内。此类调用将直接转换为对支持字段的赋值。

    我非常非常喜欢这样的功能。也许对于 C# 5...

    【讨论】:

    • 我更喜欢你的第一个例子,但不应该指定 set 关键字,即使一个属性总是有一个设置器?特别是因为 setter 可以具有不同的访问级别,即使它是 readonly(对吗?我在考虑 privateprotected。)
    • "...即使一个属性总是..." - 澄清一下,我的意思是自动属性,而不是“正常”属性。
    • @Blixt:可能。我想这意味着“它是一个自动属性,所以必须有某种方法来设置它......”我怀疑任何组合都会在某个地方变得尴尬:)
    • 我想。但是,如果将第三个代码块中的private 更改为protected 会怎样?生成该输出的简写代码应该是什么?
    • 我看到人们在其他地方要求支持只能从构造函数调用但可以修改只读变量的方法。也许二传手可能是那种功能。我不确定您在 C# 中如何称呼它们 - 托管 C++ 'initonly' 关键字实际上比 C# 的 'readonly' 关键字更具描述性。
    【解决方案4】:

    readonly只能应用于字段,所以我相信不会。

    你不能只使用:

    public readonly MyType MyProperty;
    

    因为它只能从构造函数中赋值?

    【讨论】:

    • “优秀的设计”大师会因此而杀了你,但我给你 +1 是因为它确实有效,而且在实践中似乎从来没有造成任何问题,也是为了补偿未来的投票。跨度>
    • 查看我对 Jan Bannister 的回复...有很多理由不使用公共字段,甚至是只读字段。
    【解决方案5】:

    不,你没有办法做到这一点。事实上,我不明白你为什么要获取一个以前没有设置的属性的值。出于显而易见的原因,如果既没有 set 访问器,也没有支持字段,则不能设置该值。

    【讨论】:

    • 您必须能够设置它 - 但只能从构造函数中设置,就像任何普通的只读字段一样。
    【解决方案6】:

    这真是令人费解的伙伴。

    只需将其设为公共只读字段即可。

    【讨论】:

    • 当您最终想要编写更成熟的属性实现时,您将失去属性的所有好处 - 包括源代码和二进制兼容性。公共实例字段在 IMO 中是个坏主意。
    • 我通常同意你永远不应该使用公共字段。但这是一个奇怪的用例。它是只读的,不能写入。
    • @Jan:想象一下,如果你编译你的 readonly 字段,然后它被一个只有公共 get 访问器的属性替换(它仍然可以返回 private readonly 字段的值。)这将破坏二进制兼容性。
    • @Jan:仅仅因为它是只读的并不意​​味着您最终可能不想在其中添加额外的逻辑。同样,对公开字段(它们是实现细节,与作为 API 的一部分的属性不同)的哲学反对并不会因为它是只读的而消失。不过很高兴你喜欢这本书 :)
    • 您错过了属性相对于字段的另一个优势:属性可以是接口的成员,但字段不能。
    猜你喜欢
    • 2012-09-25
    • 2011-04-15
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2018-11-12
    • 2018-12-20
    相关资源
    最近更新 更多