不可变只读引用类型和FXCop 违规:不要声明只读可变引用类型
我一直试图解决这个 FXCop 违规问题“DoNotDeclareReadOnlyMutableReferenceTypes”
MSDN:http://msdn.microsoft.com/en-us/library/ms182302%28VS.80%29.aspx
MSDN 中的代码会导致此违规:
namespace SecurityLibrary
{
public class MutableReferenceTypes
{
static protected readonly StringBuilder SomeStringBuilder;
static MutableReferenceTypes()
{
SomeStringBuilder = new StringBuilder();
}
}
}
来自 Jon 的回答 此处和此处,我了解保存对象引用的字段(在本例中为 SomeStringBuilder)是只读的并且不是对象本身(由 new StringBuilder()
创建)
因此,以这个例子为例,一旦字段引用了对象本身,我将如何更改对象本身?我喜欢 Eric Lippert 的示例说明了如何更改只读数组,并且希望看到任何其他可变引用类型的类似内容
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您不会更改对象的值。这就是规则的要点。任何声明为只读的字段实际上都应该是只读的。拥有只读可变引用是一个矛盾的说法。如果您可以更改字段“指向”的值,那么它就不再是真正的只读了。将某个对象 A 的所有成员的值分配给由字段表示的某个对象 B 或简单地将 A 分配给该字段(当它们具有相同类型时)之间实际上没有功能差异,但是当该字段时只有其中一个有效被声明为只读,但由于您可以有效地改变字段所表示的值,所以正如已经声明的那样,它并不是真正的只读
You would not change the value of the object. That's the point of the rule. Any field declared as readonly should infact be that, readonly. Having a readonly mutable reference is an oxymoron. If you Can change the value of what the field "points" to then it's not really readonly any more. There's really no functional difference between assigning the value of all members of some object A to some object B represented by a field or simply assigning A to that field (when they are of the same type) however only one of Them is valid when the field is declared readonly but since you Can effectively chage the value of what's being represented by the field it is as already stated not really readonly
只读 表示您无法更改参考帖子-建造。
FXCop 的官方立场是,它建议仅将无法修改的类型声明为
readonly
。因此,像string
这样的东西是可以的,因为对象的值无法更改。但是,StringBuilder
的值可以更改,但将其设置为只读只会阻止您在构造函数运行后将该字段分配给不同的StringBuilder
实例或null
。我不同意 FXCop 的这条规则。只要人们明白这只是一种强制措施,引用可能不会在构建后改变,那么就不会有混淆。
请注意,值类型通过 readonly 关键字变得不可变,但引用类型则不然。
readonly means you can't change the reference post-construction.
The official FXCop stance is that it recommends that only types that can't be modified should be declared
readonly
. Therefore something like astring
is okay because the value of the object can't be changed. However the value ofStringBuilder
can changed but making it readonly only prevents you from assigning the field to a differentStringBuilder
instance ornull
after the constructor runs.I disagree with FXCop on this rule. As long as one understands that this is simply an enforcement that the reference may not change post-construction then there is no confusion.
Note that value-types are made immutable by the
readonly
keyword but reference types are not.由于问题中出现了 MutableReferenceTypes 类,因此您无法真正从任何外部调用者处更改它,因为 SomeStringBuilder 字段是私有的。
然而,类本身可能会改变该字段。目前还没有,但在以后的迭代中可能会。
下面是一个示例方法:
调用 Mutate 方法将改变该类,因为 SomeStringBuilder 现在已发生更改。
不变性不仅涉及代码的当前版本,还涉及保护自己免受未来错误的影响。并不是所有类都需要是不可变的,但如果您选择创建不可变类型,保持一致是最安全的。
As the MutableReferenceTypes class is presented in the question, you can't really mutate it from any outside caller since the SomeStringBuilder field is private.
However, the class itself could mutate the field. It doesn't currently, but it could in a later iteration.
Here's an example method:
Calling the Mutate method will mutate the class because SomeStringBuilder will now have changed.
Immutability is not only about the current incarnation of your code, but also about protecting yourself from future mistakes. Not that all classes need to be immutable, but it's safest to stay consistent if you elect to create an immutable type.
.Net 有一个此处允许的不可变引用类型列表,
StringBuilder
不是其中之一。抱怨是你正在构造的东西不是不可变的,尽管静态构造函数被调用一次并且类被初始化一次,这就是所有保持不变的,其余的都是可变的。一个线程可能会调用
.Append()
,然后另一个线程......您会看到字符串构建器本身如何变化,并且不是真正的只读
,因为它不断改变状态/变化。声明它
readonly
确实是一个用词不当,因为那里引用的对象本身是不断变化的。.Net has a list of immutable reference types that are allowed here,
StringBuilder
isn't one of them.The complaint is that what you're constructing isn't immutable, though the static constructor is called once and the class is initialized once, that's all that stays the same, the rest is mutable. One thread may call
.Append()
, then another...you see how the string builder itself mutates and isn't reallyreadonly
, because it constantly changes states/mutates.Declaring it
readonly
is really a misnomer since the object referenced there itself is constantly changing.您无法更改引用,但对(可变)对象的任何调用都会更改其状态。
因此,由于
SomeStringBuilder
(在本例中)本身是可变的,因此它的内容可能会发生变化,这可能会误导该类的用户,因为它并不是真正的“只读”。基本上,readonly 不以任何方式保证对象敌人不改变,它只是说引用不改变。
You cannot change the reference, but any call on the (mutable) object changes its state.
Therefore, since the
SomeStringBuilder
(in this example) is mutable itself, its content may change, which may be misleading for users of the class because it is therefore not really "read-only".Basically,
readonly
does not in any way guarantee that the object foes not change, it merely does say that the reference does not change.