不要声明只读可变引用类型 - 为什么不呢?

时间:2010-03-03 10:12:02

标签: c# fxcop immutability readonly

我一直在阅读this question和其他一些答案,虽然我在更改引用和更改当前实例的状态之间有所不同但我不确定为什么这意味着我不应该标记它只读。这是因为标记某些东西只是告诉编译器一些关于实例的特殊内容,所以它能够将它当作线程安全处理它实际上可能不是吗?

据推测,在某些情况下我不希望实例能够被更改,但是不要介意实例的状态是否发生了变化(单例可能./ me为火焰做准备)后果是什么?如果我想要这个,那么只读标记实例吗?

4 个答案:

答案 0 :(得分:11)

没有(基于运行时/环境)的后果。编译器不会吓坏,你的运行时不会爆炸,一切都会很好。

只有FxCop(一些人使用的静态分析工具)才会对此发出警告。警告的原因在您链接的线程中解释(从语义上讲,可能不清楚对象实际上并非“只读”,只是该变量无法“重新分配”)。

就个人而言,我不同意这条规则,所以我只是禁用它(如果你正在运行FxCop并且它与你有关)。

答案 1 :(得分:8)

一个有趣的相关观点:由于类似这样的情况,可变的只读结构是一个坏主意:

http://ericlippert.com/2008/05/14/mutating-readonly-structs/

我向其展示此代码的大多数人都无法正确预测其输出。

可变的只读结构存在一个问题,即人们认为他们正在改变它们,但实际上它们正在改变副本。

可变的只读ref类型具有相反的问题。人们认为它们是不可改变的,但事实上它们只是浅薄不变。

答案 2 :(得分:7)

我认为重点是它可能会产生误导 - 一个粗心的读者可能假设一个只读变量实际上是一个常数,它不会是。

我会把它视为一个建议而不是一个规则 - 当然有可能合理的情况,但应谨慎使用。 (特别是,如果可变状态暴露在外面,我会感到紧张。)

答案 3 :(得分:4)

这两种类型的声明既有效又有用,尽管它们的含义不同:

  • 对可变对象的常量引用。
  • 对常量对象的可变引用。

如果你真的想要一个对可变对象的持续引用,那么由于任何原因被迫使用可变引用似乎是令人反感的,更不用说坏的了。在多线程编程中,常量引用可以节省您必须在拥有对象上进行同步(您仍然必须通过引用在可变对象上进行同步,但这是一个更细粒度的锁)。

粗心的读者可能也是不警惕的作家 - 对他们说不了多少:

const SourceRepository cvs = new ReadOnlyRepository(...);

C ++有一种强制指向常量对象的常量指针的方法(C ++中的引用有点不同):

Object const* const constantPointerToConstantObject = ...;

这是我在C#/ Java中遗漏的为数不多的C ++功能之一。

D有一个更好的关键字(不可变),强制传递不变性。 D的不可变性确实允许编译器进行您担心的优化并保证安全性。 D也具有非传递常数的常数,这意味着传递形式和非传递形式都是独立有用的。