我一直在努力创建一个课程,突然想到了两个代码之间有什么区别的想法:
public readonly string ProductLocation;
和
public string ProductLocation
{
get;
private set;
}
你能告诉我什么时候更好地使用以下内容吗?感谢。
答案 0 :(得分:67)
第一个是只读字段,而第二个被编译为一对方法(并且属性ProductLocation
的所有读取都被编译为对相应get
方法的调用,对它的写入被编译成对set
方法的调用;在内部,这些方法将读取/写入内部的,自动生成的非只读字段。 我说最重要的区别是线程安全性! (怎么样?继续阅读!)
该类的基本用法看起来完全相同:其他类中的代码只能读取值,而不能更改它。此外,读取值的代码看起来完全相同(例如,print(myInstace.ProductLocation)
;在这里,你不知道它是如何声明的,很酷,是吗?)
第一个,最微不足道的区别是具有私有setter的属性允许同一个类的实例修改该值,而在readonly属性的情况下,甚至对象本身都不能更改该值。
现在,对于线程安全性。当您使用多个线程时,该字段上的readonly
属性将更改其内存可见性语义(就像Java的final
一样字段)。
readonly
字段只能在声明或构造函数中指定。 分配给readonly
字段的值无法更改(至少不能以正常方式),并且保证每个线程都会在构造函数后看到正确的初始化值返回即可。因此,readonly
字段本质上是线程安全的。
要实现与属性相同的线程安全性,您必须在代码上添加一些同步,这很容易出错。根据具体情况,它可能导致死锁,数据竞争或性能下降,特别是如果您没有经验。
因此,如果值表示在对象构造之后无法更改语义的内容,则不应声明私有setter(这意味着该对象可能会更改它)。去readonly字段(并且可能声明它是私有的并声明一个只有getter访问字段的公共属性!这实际上是首选形式,因为暴露字段不好,最好只暴露方法 - 那里解释为什么在this answer)
中有很多原因答案 1 :(得分:21)
使用C# 6.0 自动属性初始化程序,可以减少样板操作
private readonly string productLocation;
public string ProductLocation { get { return productLocation; } }
哪个是
public string ProductLocation { get; }
这是只读的。仅从构造函数或内联初始化。初始化后无法编辑。 (随处可见)
但是,如果您使用私人套装;
public string ProductLocation { get; private set }
这是从外面读取的。但是可以在类本身的任何地方随时初始化。并且可以通过类本身在其生命周期内进行编辑。 (从课堂变化,从外部不变)
答案 2 :(得分:18)
通常,.NET不鼓励公开公开成员字段,这些字段应该由属性包装。所以我们假设你可能有
private readonly string productLocation;
public string ProductLocation { get { return productLocation; } }
vs
public string ProductLocation { get; private set; }
在这个设置中,忽略了人们可以通过反射完成的事情,语义是在第一种情况下,productLocation
变量只能在适当的位置和类构造函数中初始化。班上的其他成员不能改变价值。外部消费者无法设定价值。
在第二个版本中,外部消费者继续无法设置价值。但是,类本身可以随时更改值。如果您拥有的只是一个DTO(即,只传输数据的类,它没有通过方法表达的逻辑),那么这与readonly
版本基本上没有什么不同。但是,对于具有方法的类,这些方法可能会改变ProductLocation
后面的值。
如果要在构造后强制执行不可变字段的概念,请使用readonly
。但对于DTO,我可能会选择private set;
选项,主要是因为它的样板代码较少。
答案 3 :(得分:8)
第一个(使用readonly
)意味着对象甚至无法修改自己的字段值,一旦对象被实例化,其他人永远无法修改它。
第二个(使用private set
)意味着对象可以在实例化后修改其字段的值,但其他人永远不能修改它。
我会将前者用于你知道不会改变的东西,并将后者用于价值可能改变的东西,但你不希望别人改变它。
答案 4 :(得分:4)
第一个是字段,其值只能在实例化时设置 。
第二个是属性,其值可以随时设置(但仅限于其包含的对象)。
更正:属性可以由任何同一类的实例随时设置(而不仅仅是由其包含的对象)。