ram*_*ram 7 c# string fxcop readonly immutability
我一直试图围绕这个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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
从Jon 在这里和这里的答案,我理解持有对象引用的字段(在本例中为SomeStringBuilder)是readonly而不是对象本身(由其创建new StringBuilder())
所以以这个例子为例,一旦该字段引用它,我将如何更改对象本身?我喜欢Eric Lippert关于如何更改只读数组的示例,并希望看到类似于任何其他可变引用类型的内容
readonly意味着您无法在构建后更改参考.
官方的FXCop立场是它建议只应声明不能修改的类型readonly.因此像a这样的东西string是可以的,因为对象的值不能改变.但是,值StringBuilder可以更改,但只读它只会阻止您将字段分配给其他StringBuilder实例或null在构造函数运行后.
我不同意FXCop对此规则的看法.只要一个人明白这只是一个强制执行,参考可能不会在建设后改变,那么就没有混淆.
请注意,值类型由readonly关键字变为不可变,但引用类型不是.
namespace SecurityLibrary
{
public class MutableReferenceTypes
{
static protected readonly StringBuilder SomeStringBuilder;
static MutableReferenceTypes()
{
// allowed
SomeStringBuilder = new StringBuilder();
}
void Foo()
{
// not allowed
SomeStringBuilder = new StringBuilder();
}
void Bar()
{
// allowed but FXCop doesn't like this
SomeStringBuilder.AppendLine("Bar");
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于问题中出现了 MutableReferenceTypes 类,因此您无法真正从任何外部调用者处更改它,因为 SomeStringBuilder 字段是私有的。
然而,类本身可能会改变该字段。目前还没有,但在以后的迭代中可能会。
这是一个示例方法:
public static void Mutate()
{
SomeStringBuilder.AppendLine("Foo");
}
Run Code Online (Sandbox Code Playgroud)
调用 Mutate 方法将会改变该类,因为 SomeStringBuilder 现在已发生更改。
不变性不仅涉及代码的当前版本,还涉及保护自己免受未来错误的影响。并不是所有类都需要是不可变的,但如果您选择创建不可变类型,保持一致是最安全的。