关于Visual Studio 2008:C#CA2104-自动代码分析不喜欢静态只读可变类型

C# CA2104 - Automated Code Analysis dislikes static readonly mutable types

我有这样的代码:

1
2
3
4
5
6
public abstract class Base
{
    // is going to be used in deriving classes
    // let's assume foo is threadsafe
    protected static readonly Foo StaticFoo = new Foo();
}

Visual Studio 2008的代码分析弹出此消息:

CA2104 : Microsoft.Security : Remove the read-only designation from 'Base.StaticFoo' or change the field to one that is an immutable reference type. If the reference type 'Foo' is, in fact, immutable, exclude this message.

我的设计本质上存在缺陷,还是可以在源代码中添加[SuppressMessage]


问题在于它给人留下了错误的印象-它使值看起来像是不能更改,而实际上只有字段值而不是对象而不是对象。我认为代码分析在这里过于谨慎-在很多地方,您可能希望将可变类型存储在只读字段中,特别是如果它是私有的,则在静态初始化程序中进行初始化,然后再也不在代码中进行更改。

尽管该字段受到保护,但是存在派生类滥用该字段的风险。就我个人而言,我希望我所有的领域都是私有的。另一方面,我不知道您的代码-可能是您权衡了各种可能性,并认为这是正确的做法。

如果Foo确实是线程安全的,则不必担心,除了该字段为只读这一事实所带来的不变性的一般印象。我将禁用该行的警告,并添加一条注释以强调该对象是可变的,即使该字段是只读的也是如此。


Foo类型是不可变的吗?

如果不是,您是否打算仅使用此Foo对象,但能够更改其属性?如果是这种情况,那么警告只是说readonly关键字具有误导性。没有编译错误-对对象的引用是只读的,这就是您向编译器声明的内容。但是,您向其他开发人员声明的是StaticFoo是只读的,这意味着它永远不会更改。

因此,正如您所说,您可以选择。要消除此警告,请删除只读键盘,或添加SuppressMessage属性。或者,查看代码的设计。例如,将Foo实现为单例模式是否更合适?


警告告诉您,readonly修饰符仅适用于引用本身。如果Foo是引用类型,则除非您确保Foo不可变,否则您的Foo实例的状态可能仍会被修改。

在另一个节点上,当涉及到对代码进行单元测试时,类似的静态操作可能最终给您带来各种问题,因此,如果这对您来说很重要,则您可能需要考虑其他方法来实现您要尝试做的事情。