不可变只读引用类型和FXCop 违规:不要声明只读可变引用类型

发布于 2024-08-21 17:35:52 字数 1166 浏览 10 评论 0 原文

我一直试图解决这个 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 的示例说明了如何更改只读数组,并且希望看到任何其他可变引用类型的类似内容

I have been trying to wrap my head around this FXCop violation "DoNotDeclareReadOnlyMutableReferenceTypes"

MSDN: http://msdn.microsoft.com/en-us/library/ms182302%28VS.80%29.aspx

Code from MSDN which would cause this violation:

namespace SecurityLibrary
{
    public class MutableReferenceTypes
    {
        static protected readonly StringBuilder SomeStringBuilder;

        static MutableReferenceTypes()
        {
            SomeStringBuilder = new StringBuilder();
        }
    }
}

From Jon's answer here and here , I understand that the field holding the reference to the object (in this case SomeStringBuilder) is readonly and not the object itself (which is created by new StringBuilder() )

So taking this example, how would I change the object itself, once the field has a reference to it ? I like Eric Lippert's example of how the readonly array can be changed, and would like to see something similar for any other mutable reference type

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

归属感 2024-08-28 17:35:53

您不会更改对象的值。这就是规则的要点。任何声明为只读的字段实际上都应该是只读的。拥有只读可变引用是一个矛盾的说法。如果您可以更改字段“指向”的值,那么它就不再是真正的只读了。将某个对象 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

酷遇一生 2024-08-28 17:35:52

只读 表示您无法更改参考帖子-建造。

FXCop 的官方立场是,它建议仅将无法修改的类型声明为readonly。因此,像 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");
        }
    }
}

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 a string is okay because the value of the object can't be changed. However the value of StringBuilder can changed but making it readonly only prevents you from assigning the field to a different StringBuilder instance or null 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.

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");
        }
    }
}
情释 2024-08-28 17:35:52

由于问题中出现了 MutableReferenceTypes 类,因此您无法真正从任何外部调用者处更改它,因为 SomeStringBuilder 字段是私有的。

然而,类本身可能会改变该字段。目前还没有,但在以后的迭代中可能会。

下面是一个示例方法:

public static void Mutate()
{
    SomeStringBuilder.AppendLine("Foo");
}

调用 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:

public static void Mutate()
{
    SomeStringBuilder.AppendLine("Foo");
}

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.

节枝 2024-08-28 17:35:52

.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 really readonly, because it constantly changes states/mutates.

Declaring it readonly is really a misnomer since the object referenced there itself is constantly changing.

眉黛浅 2024-08-28 17:35:52

您无法更改引用,但对(可变)对象的任何调用都会更改其状态。

因此,由于 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, readonlydoes not in any way guarantee that the object foes not change, it merely does say that the reference does not change.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文