当前位置:  开发笔记 > 编程语言 > 正文

在C#中将字段标记为"只读"有什么好处?

如何解决《在C#中将字段标记为"只读"有什么好处?》经验,为你挑选了7个好方法。

将成员变量声明为只读有什么好处?它只是防止在类的生命周期中更改某些人,或者是否由于此关键字而导致编译器速度提高



1> JaredPar..:

我不认为使用只读字段会有任何性能提升.它只是一个检查,以确保一旦完全构造对象,该字段不能指向新值.

然而,"readonly"与其他类型的只读语义非常不同,因为它在运行时由CLR强制执行.readonly关键字编译为.initonly,可由CLR验证.

此关键字的真正优势是生成不可变数据结构.根据定义,不可变数据结构一旦构造就不能改变.这使得在运行时很容易推断出结构的行为.例如,没有将不可变结构传递给另一个随机代码部分的危险.它们无法改变它,因此您可以针对该结构进行可靠编程.

这是关于不变性的一个好处的一个很好的条目:线程


如果您阅读此内容,可以修改http://stackoverflow.com/questions/9860595/prevent-changing-the-value-of-string-empty只读成员,看起来像.net的行为不一致

2> Bill the Liz..:

readonly关键字用于将成员变量声明为常量,但允许在运行时计算该值.这与使用const修饰符声明的常量不同,后者必须在编译时设置其值.使用readonly您可以在声明中或在该字段所属的对象的构造函数中设置字段的值.

如果您不想重新编译引用该常量的外部DLL(因为它在编译时被替换),也可以使用它.



3> Xiaofu..:

使用没有明显的性能优势readonly,至少没有任何我曾经见过的提及.这只是为了完全按照您的建议进行操作,以防止在初始化后进行修改.

因此它有益于它可以帮助您编写更强大,更易读的代码.当你在团队中工作或进行维护时,这种事情的真正好处就来了.声明某些readonly内容类似于在代码中为该变量的使用设置合同.可以把它想象为添加文档的方式与其他关键字一样,internal或者private说,"这个变量在初始化后不应该被修改",而且你要强制执行它.

因此,如果您创建一个类并按readonly设计标记某些成员变量,那么您可以防止自己或其他团队成员在以后扩展或修改您的类时犯错误.在我看来,这是一个值得拥有的好处(以额外的语言复杂性为代价,如评论中提到的那样).


在我看来,这个答案和讨论实际上是最好的答案+1
我同意,但我认为真正的好处来自不止一个人正在研究代码.这就像在代码中有一个小的设计声明,它的使用合同.我应该把它放在答案中,呵呵.

4> Daniel Auger..:

用非常实际的方式来说:

如果在dll中使用const,而dll B引用该const,则该const的值将被编译为dll B.如果使用该const的新值重新部署dll A,则dll B仍将使用原始值.

如果在readllly中使用read readly in dll A和dll B引用,则readonly将始终在运行时查找.这意味着如果您为该readonly重新部署具有新值的dll A,则dll B将使用该新值.


这是理解差异的一个很好的实际例子.谢谢.
我认为这个答案缺少最大的实用术语:将运行时计算的值存储到“只读”字段中的能力。您不能在const中存储`new object();`,这是有道理的,因为您不能在编译期间将诸如非引用之类的非值对象烘烤到其他程序集中,而无需更改标识。

5> 小智..:

存在一种可能的情况,即编译器可以基于readonly关键字的存在来进行性能优化.

这仅适用于readonly字段也标记为静态的情况.在这种情况下,JIT编译器可以假设此静态字段永远不会更改.编译类的方法时,JIT编译器可以将此考虑在内.

典型示例:您的类可以具有在构造函数中初始化的静态只读IsDebugLoggingEnabled字段(例如,基于配置文件).一旦实际的方法被JIT编译,编译器可能会在未启用调试日志记录时省略代码的整个部分.

我还没有检查这个优化是否实际在JIT编译器的当前版本中实现,所以这只是推测.


事实上,当前的JIT编译器确实实现了这一点,并且自CLR 3.5起实施.https://github.com/dotnet/coreclr/issues/1079

6> Brian Rasmus..:

请记住,readonly仅适用于值本身,因此如果您使用引用类型readonly只保护引用不被更改.实例的状态不受readonly的保护.



7> Adam Naylor..:

不要忘记有一种解决方法可以readonly使用outparams 将字段设置在任何构造函数之外.

有点凌乱但是:

private readonly int _someNumber;
private readonly string _someText;

public MyClass(int someNumber) : this(data, null)
{ }

public MyClass(int someNumber, string someText)
{
    Initialise(out _someNumber, someNumber, out _someText, someText);
}

private void Initialise(out int _someNumber, int someNumber, out string _someText, string someText)
{
    //some logic
}

在此进一步讨论:http://www.adamjamesnaylor.com/2013/01/23/Setting-Readonly-Fields-From-Chained-Constructors.aspx


这些字段仍在构造函数中分配。.没有“解决”的问题。值是来自单个表达式,分解的复杂类型还是通过调用out的引用语义分配都没有关系。
推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有