将成员变量声明为只读有什么好处?它只是防止在类的生命周期中更改某些人,或者是否由于此关键字而导致编译器速度提高
我不认为使用只读字段会有任何性能提升.它只是一个检查,以确保一旦完全构造对象,该字段不能指向新值.
然而,"readonly"与其他类型的只读语义非常不同,因为它在运行时由CLR强制执行.readonly关键字编译为.initonly,可由CLR验证.
此关键字的真正优势是生成不可变数据结构.根据定义,不可变数据结构一旦构造就不能改变.这使得在运行时很容易推断出结构的行为.例如,没有将不可变结构传递给另一个随机代码部分的危险.它们无法改变它,因此您可以针对该结构进行可靠编程.
这是关于不变性的一个好处的一个很好的条目:线程
该readonly
关键字用于将成员变量声明为常量,但允许在运行时计算该值.这与使用const
修饰符声明的常量不同,后者必须在编译时设置其值.使用readonly
您可以在声明中或在该字段所属的对象的构造函数中设置字段的值.
如果您不想重新编译引用该常量的外部DLL(因为它在编译时被替换),也可以使用它.
使用没有明显的性能优势readonly
,至少没有任何我曾经见过的提及.这只是为了完全按照您的建议进行操作,以防止在初始化后进行修改.
因此它有益于它可以帮助您编写更强大,更易读的代码.当你在团队中工作或进行维护时,这种事情的真正好处就来了.声明某些readonly
内容类似于在代码中为该变量的使用设置合同.可以把它想象为添加文档的方式与其他关键字一样,internal
或者private
说,"这个变量在初始化后不应该被修改",而且你要强制执行它.
因此,如果您创建一个类并按readonly
设计标记某些成员变量,那么您可以防止自己或其他团队成员在以后扩展或修改您的类时犯错误.在我看来,这是一个值得拥有的好处(以额外的语言复杂性为代价,如评论中提到的那样).
用非常实际的方式来说:
如果在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将使用该新值.
存在一种可能的情况,即编译器可以基于readonly关键字的存在来进行性能优化.
这仅适用于readonly字段也标记为静态的情况.在这种情况下,JIT编译器可以假设此静态字段永远不会更改.编译类的方法时,JIT编译器可以将此考虑在内.
典型示例:您的类可以具有在构造函数中初始化的静态只读IsDebugLoggingEnabled字段(例如,基于配置文件).一旦实际的方法被JIT编译,编译器可能会在未启用调试日志记录时省略代码的整个部分.
我还没有检查这个优化是否实际在JIT编译器的当前版本中实现,所以这只是推测.
请记住,readonly仅适用于值本身,因此如果您使用引用类型readonly只保护引用不被更改.实例的状态不受readonly的保护.
不要忘记有一种解决方法可以readonly
使用out
params 将字段设置在任何构造函数之外.
有点凌乱但是:
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