2

来自 C# 4.0 第 7.5.5 节。

如果 M 是在值类型中声明的实例函数成员:

  • [...]
  • 如果 E 未被分类为变量,则创建 E 类型的临时局部变量并将 E 的值分配给该变量。然后将 E 重新分类为对该临时局部变量的引用。临时变量可以在 M 中作为 this 访问,但不能以任何其他方式访问。因此,只有当 E 是真正的变量什么是真正的变量...?)时,调用者才有可能观察到 M 对此所做的更改。

Eric Lippert 继续说:

这一点说明了可变性和按值复制语义的组合可能导致麻烦的另一种方式。例如,在构造函数运行后,只读字段不会被归类为变量。因此,尝试调用改变值类型的只读字段内容的方法会成功,但实际上会改变副本!通过完全避免可变值类型来避免这些问题。

如何重现 Eric 描述的场景?我尝试了以下。正如我所料,它出错了:

    struct A
    {
        public readonly int mutableReadonlyField;

        public A(int originalValue)
        {
            mutableReadonlyField = originalValue;
        }

        public A MethodThatMutatesTheContentsOfAReadOnlyField(int mutate)
        {            
            this.mutableReadonlyField = mutate;//Constructor has run so mutableReadonlyField is a temporary local variable
            //ERROR: A readonly field cannot be assigned to (except in a constructor or a variable initializer)

            A newA = this;//Is this a true variable?
            return newA;
        }
}
4

1 回答 1

5

我在我的博客上举了一个例子:

http://ericlippert.com/2008/05/14/mutating-readonly-structs/

问题是我的句子片段“值类型的只读字段”是模棱两可和误导的。我打算将其表示为值类型为 S的中的只读字段,但显然更自然的阅读是将其视为S 本身中的只读字段。我应该完全改写这句话。为错误道歉。

回答你的另一个问题:形容词“真”是不必要的。如果这句话只是说“因此,只有当 E 是一个变量时,调用者才有可能观察到 M 对此所做的更改。

于 2013-02-19T15:12:36.213 回答