来自 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;
}
}