将成员变量声明为只读有哪些好处?它只是为了防止在类的生命周期中有人更改它的值,还是使用这个关键字会导致任何速度或效率的改进?


当前回答

小心使用私有只读数组。如果客户端将这些对象作为对象公开(您可以像我一样为COM互操作这样做),客户端可以操作数组值。当将数组作为对象返回时,请使用Clone()方法。

其他回答

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

这仅适用于只读字段也标记为静态的情况。在这种情况下,JIT编译器可以假设这个静态字段永远不会改变。JIT编译器在编译类的方法时可以考虑到这一点。

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

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

令人惊讶的是,只读实际上会导致代码变慢,正如Jon Skeet在测试他的Noda Time库时发现的那样。在本例中,一个在20秒内运行的测试在删除readonly后只花了4秒。

https://codeblog.jonskeet.uk/2014/07/16/micro-optimization-the-surprising-inefficiency-of-readonly-fields/

小心使用私有只读数组。如果客户端将这些对象作为对象公开(您可以像我一样为COM互操作这样做),客户端可以操作数组值。当将数组作为对象返回时,请使用Clone()方法。

请记住,readonly只应用于值本身,所以如果您使用引用类型,readonly只保护引用不被更改。实例的状态不受只读保护。

添加一个基本方面来回答这个问题:

属性可以通过省略set操作符来表示为只读。所以在大多数情况下,你不需要添加readonly关键字属性:

public int Foo { get; }  // a readonly property

相比之下:字段需要readonly关键字来实现类似的效果:

public readonly int Foo; // a readonly field

因此,将字段标记为只读的一个好处是可以实现与没有设置操作符的属性类似的写保护级别——如果出于某种原因,不需要将字段更改为属性。