4

我有这样的代码:

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]在源代码中添加一个?

4

3 回答 3

8

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

然而,虽然该字段受到保护,但派生类滥用它的风险更大。就我个人而言,我喜欢我所有的领域都是私有的。另一方面,我不知道您的代码 - 可能是您已经权衡了可能性并认为这是正确的做法。

如果Foo真的是线程安全的,那么除了字段是只读的这一事实所给出的不变性的一般印象之外,就不用担心了。我将禁用该行的警告,并添加注释以强调该对象是可变的,即使该字段是只读的。

于 2009-03-27T07:37:34.173 回答
3

Foo 类型是不可变的吗?

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

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

于 2009-03-27T07:36:06.207 回答
1

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

在另一个节点上,当涉及到对代码进行单元测试时,像这样的静态可能最终会给您带来各种问题,因此如果这对您很重要,您可能想看看其他方法来实现您想要做的事情.

于 2009-03-27T07:34:24.370 回答